Exemple #1
0
 public void RegisterSuccessfulTimestamp(int frameNo, IVtiTimeStamp oddFieldOSD, IVtiTimeStamp evenFieldOSD, DateTime oddFieldTimestamp, DateTime evenFieldTimestamp)
 {
     m_PrevFrameNo      = frameNo;
     m_PrevOddTicks     = oddFieldTimestamp.Ticks;
     m_PrevEvenTicks    = evenFieldTimestamp.Ticks;
     m_PrevOddFieldNo   = oddFieldOSD.FrameNumber;
     m_PrevEvenFieldNo  = evenFieldOSD.FrameNumber;
     m_PrevOddFieldOSD  = new VtiTimeStamp(oddFieldOSD);
     m_PrevEvenFieldOSD = new VtiTimeStamp(evenFieldOSD);
 }
Exemple #2
0
 public static long GetTicks(this IVtiTimeStamp x)
 {
     return(new DateTime(Math.Max(1, x.Year), 1, 1)
            .AddMonths(Math.Max(1, x.Month) - 1)
            .AddDays(Math.Max(1, x.Day) - 1)
            .AddHours(x.Hours)
            .AddMinutes(x.Minutes)
            .AddSeconds(x.Seconds)
            .AddMilliseconds(x.Milliseconds10 / 10.0)
            .Ticks);
 }
Exemple #3
0
 public static string AsFullString(this IVtiTimeStamp x)
 {
     if (x.ContainsDate)
     {
         return(string.Format("{0}-{1:00}-{2:00} {3}", x.Year, x.Month, x.Day, x.AsString()));
     }
     else
     {
         return(x.AsString());
     }
 }
Exemple #4
0
 public static string AsString(this IVtiTimeStamp x)
 {
     if (x.ContainsFrameNumbers)
     {
         return(string.Format("{0:00}:{1:00}:{2:00}.{3:0000} FrmNo:{4}", x.Hours, x.Minutes, x.Seconds, x.Milliseconds10, x.FrameNumber));
     }
     else
     {
         return(string.Format("{0:00}:{1:00}:{2:00}.{3:0000}", x.Hours, x.Minutes, x.Seconds, x.Milliseconds10));
     }
 }
Exemple #5
0
 internal DateTime ExtractDateTime(int frameNo, int frameStep, IVtiTimeStamp oddFieldOSD, IVtiTimeStamp evenFieldOSD, out string failedReason)
 {
     if (m_DuplicatedFields)
     {
         return(ExtractDateTimeDuplicateFields(frameNo, frameStep, oddFieldOSD, evenFieldOSD, out failedReason));
     }
     else
     {
         return(ExtractDateTimeBothFields(frameNo, frameStep, oddFieldOSD, evenFieldOSD, out failedReason));
     }
 }
Exemple #6
0
        public VtiTimeStamp(IVtiTimeStamp timeStamp)
        {
            Hours                = timeStamp.Hours;
            Minutes              = timeStamp.Minutes;
            Seconds              = timeStamp.Seconds;
            Milliseconds10       = timeStamp.Milliseconds10;
            FrameNumber          = timeStamp.FrameNumber;
            ContainsFrameNumbers = timeStamp.ContainsFrameNumbers;

            ContainsDate = timeStamp.ContainsDate;
            Year         = timeStamp.Year;
            Month        = timeStamp.Month;
            Day          = timeStamp.Day;
        }
Exemple #7
0
 public static bool HoursMinSecMilliEquals(this IVtiTimeStamp x, IVtiTimeStamp y)
 {
     return(x.Hours == y.Hours && x.Minutes == y.Minutes && x.Seconds == y.Seconds && x.Milliseconds10 == y.Milliseconds10);
 }
Exemple #8
0
        internal DateTime ExtractDateTimeBothFields(int frameNo, int frameStep, IVtiTimeStamp oddFieldOSD, IVtiTimeStamp evenFieldOSD, out string failedReason)
        {
            bool failedValidation = false;

            failedReason = null;

            if (oddFieldOSD == null || evenFieldOSD == null)
            {
                return(DateTime.MinValue);
            }

            if (frameStep != m_FrameStep)
            {
                m_FrameStep = frameStep;
                m_Corrector.Reset(m_VideoFormat);
            }

            if (oddFieldOSD.ContainsFrameNumbers)
            {
                if (oddFieldOSD.FrameNumber != evenFieldOSD.FrameNumber - 1 &&
                    oddFieldOSD.FrameNumber != evenFieldOSD.FrameNumber + 1)
                {
                    // Video fields are not consequtive
                    failedValidation = true;
                    failedReason     = "Video fields are not consequtive";
                }
            }


            try
            {
                DateTime oddFieldTimestamp = oddFieldOSD.ContainsDate
                    ? new DateTime(oddFieldOSD.Year, oddFieldOSD.Month, oddFieldOSD.Day, oddFieldOSD.Hours, oddFieldOSD.Minutes, oddFieldOSD.Seconds).AddMilliseconds(Math.Min(10000, oddFieldOSD.Milliseconds10) / 10.0f)
                    : new DateTime(1, 1, 1, oddFieldOSD.Hours, oddFieldOSD.Minutes, oddFieldOSD.Seconds).AddMilliseconds(Math.Min(10000, oddFieldOSD.Milliseconds10) / 10.0f);

                DateTime evenFieldTimestamp = evenFieldOSD.ContainsDate
                    ?  new DateTime(evenFieldOSD.Year, evenFieldOSD.Month, evenFieldOSD.Day, evenFieldOSD.Hours, evenFieldOSD.Minutes, evenFieldOSD.Seconds).AddMilliseconds(Math.Min(10000, evenFieldOSD.Milliseconds10) / 10.0f)
                    :  new DateTime(1, 1, 1, evenFieldOSD.Hours, evenFieldOSD.Minutes, evenFieldOSD.Seconds).AddMilliseconds(Math.Min(10000, evenFieldOSD.Milliseconds10) / 10.0f);

                double fieldDuration = Math.Abs(new TimeSpan(oddFieldTimestamp.Ticks - evenFieldTimestamp.Ticks).TotalMilliseconds);

                if (m_VideoFormat == VideoFormat.PAL &&
                    (Math.Abs(fieldDuration - FIELD_DURATION_PAL) > 1.0))
                {
                    // PAL field is not 20 ms
                    failedValidation = true;
                    failedReason     = string.Format("PAL field is not 20 ms. It is {0} ms. ", fieldDuration);
                }

                if (m_VideoFormat == VideoFormat.NTSC &&
                    (Math.Abs(fieldDuration - FIELD_DURATION_NTSC) > 1.0))
                {
                    // NTSC field is not 16.68 ms
                    failedValidation = true;
                    failedReason     = string.Format("NTSC field is not 16.68 ms. It is {0} ms. ", fieldDuration);
                }

                int oddEvenFieldDirection = oddFieldTimestamp.Ticks - evenFieldTimestamp.Ticks < 0 ? -1 : 1;
                if (m_Corrector.OddEvenFieldDirectionIsKnown() &&
                    oddEvenFieldDirection != m_Corrector.GetOddEvenFieldDirection())
                {
                    // Field timestamps are wrong have changed order (did they swap)?
                    failedValidation = true;
                    failedReason    += "Field timestamps are wrong have changed order (did they swap)? ";
                }

                if (Math.Max(m_Corrector.m_PrevOddTicks, m_Corrector.m_PrevEvenTicks) > Math.Min(oddFieldTimestamp.Ticks, evenFieldTimestamp.Ticks))
                {
                    failedValidation = true;
                    failedReason    += "Field timestamps are earlier than previous timestamps. ";
                }

                if (failedValidation)
                {
                    string correctionInfo;
                    failedValidation = !m_Corrector.TryToCorrect(frameNo, frameStep, null, oddFieldOSD, evenFieldOSD, m_EvenBeforeOdd, ref oddFieldTimestamp, ref evenFieldTimestamp, out correctionInfo);
                    failedReason    += ". " + correctionInfo;
                }

                if (failedValidation)
                {
                    string errorText = string.Format("OCR ERR: FrameNo: {0}, Odd Timestamp: {1}:{2}:{3}.{4} {5}, Even Timestamp: {6}:{7}:{8}.{9} {10}, {11}",
                                                     frameNo, oddFieldOSD.Hours, oddFieldOSD.Minutes, oddFieldOSD.Seconds, oddFieldOSD.Milliseconds10, oddFieldOSD.FrameNumber,
                                                     evenFieldOSD.Hours, evenFieldOSD.Minutes, evenFieldOSD.Seconds, evenFieldOSD.Milliseconds10, evenFieldOSD.FrameNumber, failedReason);

                    Trace.WriteLine(errorText);

                    if (m_CalibrationErrorProcessor.ErrorCount < 16)
                    {
                        var copy = new List <uint>();
                        copy.AddRange(m_GetCurrImageQuery());
                        m_CalibrationErrorProcessor.AddErrorImage(string.Format("ocrerr_{0}.bmp", frameNo), copy.ToArray(), 0, 0);
                        m_CalibrationErrorProcessor.AddErrorText(errorText);
                    }

                    if (m_VideoController != null)
                    {
                        m_VideoController.RegisterOcrError();
                    }

                    m_Corrector.RegisterUnsuccessfulTimestamp(frameNo, fieldDuration, frameStep, null);
                }
                else
                {
                    m_Corrector.RegisterSuccessfulTimestamp(frameNo, oddFieldOSD, evenFieldOSD, oddFieldTimestamp, evenFieldTimestamp);
                }

                if (failedValidation)
                {
                    return(DateTime.MinValue);
                }
                failedReason = null;

                if (oddFieldOSD.ContainsFrameNumbers)
                {
                    if (oddFieldOSD.FrameNumber == evenFieldOSD.FrameNumber - 1)
                    {
                        return(oddFieldTimestamp);
                    }
                    else
                    {
                        return(evenFieldTimestamp);
                    }
                }
                else
                {
                    if (m_EvenBeforeOdd)
                    {
                        return(evenFieldTimestamp);
                    }
                    else
                    {
                        return(oddFieldTimestamp);
                    }
                }
            }
            catch (Exception ex)
            {
                Trace.WriteLine(ex.GetFullStackTrace());

                if (m_VideoController != null)
                {
                    m_VideoController.RegisterOcrError();
                }

                return(DateTime.MinValue);
            }
        }
Exemple #9
0
        internal DateTime ExtractAAVDateTime(int frameNo, int frameStep, IVtiTimeStamp oddFieldOSD, IVtiTimeStamp evenFieldOSD, out string failedReason)
        {
            bool failedValidation = false;

            failedReason = null;

            if (oddFieldOSD == null || evenFieldOSD == null)
            {
                return(DateTime.MinValue);
            }

            int integratedAavFields = 2 * m_IntegratedAAVFrames;

            if (oddFieldOSD.ContainsFrameNumbers)
            {
                if (oddFieldOSD.FrameNumber != evenFieldOSD.FrameNumber - integratedAavFields + 1 &&
                    oddFieldOSD.FrameNumber != evenFieldOSD.FrameNumber + integratedAavFields - 1)
                {
                    // Video fields are not consequtive
                    failedValidation = true;
                    failedReason     = "Integration interval is incomplete";
                }
            }

            try
            {
                //   | e               e |        |   o              o|
                //   |.e.o|.e.o|.e.o|.e.o|        |.e.o|.e.o|.e.o|.e.o|

                DateTime oddFieldTimestamp  = new DateTime(1, 1, 1, oddFieldOSD.Hours, oddFieldOSD.Minutes, oddFieldOSD.Seconds).AddMilliseconds(Math.Min(10000, oddFieldOSD.Milliseconds10) / 10.0f);
                DateTime evenFieldTimestamp = new DateTime(1, 1, 1, evenFieldOSD.Hours, evenFieldOSD.Minutes, evenFieldOSD.Seconds).AddMilliseconds(Math.Min(10000, evenFieldOSD.Milliseconds10) / 10.0f);

                double integrationPeriodDuration = Math.Abs(new TimeSpan(oddFieldTimestamp.Ticks - evenFieldTimestamp.Ticks).TotalMilliseconds);
                double fieldDuration;
                if (m_VideoFormat != null)
                {
                    if (m_VideoFormat == VideoFormat.PAL)
                    {
                        fieldDuration = (integrationPeriodDuration + FIELD_DURATION_PAL) / integratedAavFields;
                        if ((Math.Abs(fieldDuration - FIELD_DURATION_PAL) > 1.0))
                        {
                            // PAL field is not 20 ms
                            failedValidation = true;
                            failedReason     = string.Format("PAL field is not 20 ms. It is {0} ms", fieldDuration);
                        }
                    }
                    else if (m_VideoFormat == VideoFormat.NTSC)
                    {
                        fieldDuration = (integrationPeriodDuration + FIELD_DURATION_NTSC) / integratedAavFields;
                        if (Math.Abs(fieldDuration - FIELD_DURATION_NTSC) > 1.0)
                        {
                            // NTSC field is not 16.68 ms
                            failedValidation = true;
                            failedReason     = string.Format("NTSC field is not 16.68 ms. It is {0} ms", fieldDuration);
                        }
                    }
                    else
                    {
                        throw new ApplicationException("AAV videos must be PAL or NTSC.");
                    }
                }
                else
                {
                    throw new ApplicationException("Cannot identify the native format of an AAV video.");
                }

                if (failedValidation)
                {
                    string correctionInfo;
                    failedValidation = !m_Corrector.TryToCorrect(frameNo, frameStep, integratedAavFields, oddFieldOSD, evenFieldOSD, m_EvenBeforeOdd, ref oddFieldTimestamp, ref evenFieldTimestamp, out correctionInfo);
                    failedReason    += ". " + correctionInfo;
                }

                if (failedValidation)
                {
                    string errorText = string.Format("OCR ERR: FrameNo: {0}, Odd Timestamp: {1}:{2}:{3}.{4} {5}, Even Timestamp: {6}:{7}:{8}.{9} {10}, {11}",
                                                     frameNo, oddFieldOSD.Hours, oddFieldOSD.Minutes, oddFieldOSD.Seconds, oddFieldOSD.Milliseconds10, oddFieldOSD.FrameNumber,
                                                     evenFieldOSD.Hours, evenFieldOSD.Minutes, evenFieldOSD.Seconds, evenFieldOSD.Milliseconds10, evenFieldOSD.FrameNumber, failedReason);

                    Trace.WriteLine(errorText);

                    if (m_CalibrationErrorProcessor.ErrorCount < 16)
                    {
                        var copy = new List <uint>();
                        copy.AddRange(m_GetCurrImageQuery());
                        m_CalibrationErrorProcessor.AddErrorImage(string.Format("ocrerr_{0}.bmp", frameNo), copy.ToArray(), 0, 0);
                        m_CalibrationErrorProcessor.AddErrorText(errorText);
                    }

                    if (m_VideoController != null)
                    {
                        m_VideoController.RegisterOcrError();
                    }

                    m_Corrector.RegisterUnsuccessfulTimestamp(frameNo, fieldDuration, frameStep, integratedAavFields);
                }
                else
                {
                    m_Corrector.RegisterSuccessfulTimestamp(frameNo, oddFieldOSD, evenFieldOSD, oddFieldTimestamp, evenFieldTimestamp);
                }

                if (oddFieldOSD.ContainsFrameNumbers)
                {
                    if (oddFieldOSD.FrameNumber == evenFieldOSD.FrameNumber - integratedAavFields + 1)
                    {
                        return(failedValidation ? DateTime.MinValue : oddFieldTimestamp);
                    }
                    else
                    {
                        return(failedValidation ? DateTime.MinValue : evenFieldTimestamp);
                    }
                }
                else
                {
                    if (failedValidation)
                    {
                        return(DateTime.MinValue);
                    }

                    if (m_EvenBeforeOdd)
                    {
                        return(evenFieldTimestamp);
                    }
                    else
                    {
                        return(oddFieldTimestamp);
                    }
                }
            }
            catch (Exception ex)
            {
                Trace.WriteLine(ex.GetFullStackTrace());

                return(DateTime.MinValue);
            }
        }
Exemple #10
0
        internal DateTime ExtractDateTimeDuplicateFields(int frameNo, int frameStep, IVtiTimeStamp oddFieldOSD, IVtiTimeStamp evenFieldOSD, out string failedReason)
        {
            bool failedValidation = false;

            failedReason = null;

            if (oddFieldOSD == null || evenFieldOSD == null)
            {
                return(DateTime.MinValue);
            }

            if (frameStep != m_FrameStep)
            {
                m_FrameStep = frameStep;
                m_Corrector.Reset(m_VideoFormat);
            }

            try
            {
                DateTime frameTimestamp1 = oddFieldOSD.ContainsDate
                    ? new DateTime(oddFieldOSD.Year, oddFieldOSD.Month, oddFieldOSD.Day, oddFieldOSD.Hours, oddFieldOSD.Minutes, oddFieldOSD.Seconds).AddMilliseconds(Math.Min(10000, oddFieldOSD.Milliseconds10) / 10.0f)
                    : new DateTime(1, 1, 1, oddFieldOSD.Hours, oddFieldOSD.Minutes, oddFieldOSD.Seconds).AddMilliseconds(Math.Min(10000, oddFieldOSD.Milliseconds10) / 10.0f);

                DateTime frameTimestamp2 = evenFieldOSD.ContainsDate
                    ? new DateTime(evenFieldOSD.Year, evenFieldOSD.Month, evenFieldOSD.Day, evenFieldOSD.Hours, evenFieldOSD.Minutes, evenFieldOSD.Seconds).AddMilliseconds(Math.Min(10000, evenFieldOSD.Milliseconds10) / 10.0f)
                    : new DateTime(1, 1, 1, evenFieldOSD.Hours, evenFieldOSD.Minutes, evenFieldOSD.Seconds).AddMilliseconds(Math.Min(10000, evenFieldOSD.Milliseconds10) / 10.0f);

                double equalityCheck = Math.Abs(new TimeSpan(frameTimestamp1.Ticks - frameTimestamp2.Ticks).TotalMilliseconds);

                if (Math.Abs(equalityCheck) > 1.0)
                {
                    // The OCR of the two identical fields has returned different result. This could happen
                    failedValidation = true;
                    failedReason     = "The timestamps of identical video fields are not the same. ";
                }

                double frameDuration = 0;
                if (m_Corrector.m_PrevOddTicks != -1)
                {
                    if (Math.Max(m_Corrector.m_PrevOddTicks, m_Corrector.m_PrevEvenTicks) > Math.Min(frameTimestamp1.Ticks, frameTimestamp2.Ticks))
                    {
                        failedValidation = true;
                        failedReason    += "Field timestamps are earlier than previous timestamps. ";
                    }

                    frameDuration = Math.Abs(new TimeSpan(m_Corrector.m_PrevOddTicks - frameTimestamp1.Ticks).TotalMilliseconds);

                    if (m_VideoFormat == VideoFormat.PAL &&
                        (Math.Abs(frameDuration - FRAME_DURATION_PAL) > 1.0))
                    {
                        // PAL field is not 20 ms
                        failedValidation = true;
                        failedReason     = string.Format("PAL field is not 40 ms. It is {0} ms. ", frameDuration);
                    }

                    if (m_VideoFormat == VideoFormat.NTSC &&
                        (Math.Abs(frameDuration - FRAME_DURATION_NTSC) > 1.0))
                    {
                        // NTSC field is not 16.68 ms
                        failedValidation = true;
                        failedReason     = string.Format("NTSC field is not 33.36 ms. It is {0} ms. ", frameDuration);
                    }

                    if (failedValidation)
                    {
                        string correctionInfo;
                        failedValidation = !m_Corrector.TryToCorrectDuplicateField(frameNo, frameStep, oddFieldOSD, evenFieldOSD, ref frameTimestamp1, out correctionInfo);
                        frameTimestamp2  = frameTimestamp1;
                        failedReason    += ". " + correctionInfo;
                    }
                }
                else
                {
                    // If this is the first time we extract, make sure duration is correct, before registering it as successful
                    var fieldDuration = (((GpxBoxSpriteVtiTimeStamp)oddFieldOSD).Milliseconds10First - ((GpxBoxSpriteVtiTimeStamp)oddFieldOSD).Milliseconds10Second) / 10.0;
                    if (fieldDuration < 0)
                    {
                        fieldDuration += 1000;
                    }

                    if (m_VideoFormat == VideoFormat.PAL &&
                        (Math.Abs(fieldDuration - FIELD_DURATION_PAL) > 1.0))
                    {
                        // PAL field is not 20.00 ms
                        failedValidation = true;
                        failedReason     = string.Format("PAL field of first OCR-ed frame is not 20.00 ms. It is {0} ms. ", frameDuration);
                    }

                    if (m_VideoFormat == VideoFormat.NTSC &&
                        (Math.Abs(fieldDuration - FIELD_DURATION_NTSC) > 1.0))
                    {
                        // NTSC field is not 16.68 ms
                        failedValidation = true;
                        failedReason     = string.Format("NTSC field of first OCR-ed frame is not 33.36 ms. It is {0} ms. ", frameDuration);
                    }
                }

                if (failedValidation)
                {
                    string errorText = string.Format("OCR ERR: FrameNo: {0}, Odd Timestamp: {1}:{2}:{3}.{4} {5}, Even Timestamp: {6}:{7}:{8}.{9} {10}, {11}",
                                                     frameNo, oddFieldOSD.Hours, oddFieldOSD.Minutes, oddFieldOSD.Seconds, oddFieldOSD.Milliseconds10, oddFieldOSD.FrameNumber,
                                                     evenFieldOSD.Hours, evenFieldOSD.Minutes, evenFieldOSD.Seconds, evenFieldOSD.Milliseconds10, evenFieldOSD.FrameNumber, failedReason);

                    Trace.WriteLine(errorText);

                    if (m_CalibrationErrorProcessor.ErrorCount < 16)
                    {
                        var copy = new List <uint>();
                        copy.AddRange(m_GetCurrImageQuery());
                        m_CalibrationErrorProcessor.AddErrorImage(string.Format("ocrerr_{0}.bmp", frameNo), copy.ToArray(), 0, 0);
                        m_CalibrationErrorProcessor.AddErrorText(errorText);
                    }

                    if (m_VideoController != null)
                    {
                        m_VideoController.RegisterOcrError();
                    }

                    m_Corrector.RegisterUnsuccessfulTimestamp(frameNo, frameDuration / 2.0, frameStep, null);
                }
                else
                {
                    m_Corrector.RegisterSuccessfulTimestamp(frameNo, oddFieldOSD, evenFieldOSD, frameTimestamp1, frameTimestamp1);
                }

                if (failedValidation)
                {
                    return(DateTime.MinValue);
                }
                failedReason = null;

                return(frameTimestamp1);
            }
            catch (Exception ex)
            {
                Trace.WriteLine(ex.GetFullStackTrace());

                if (m_VideoController != null)
                {
                    m_VideoController.RegisterOcrError();
                }

                return(DateTime.MinValue);
            }
        }
Exemple #11
0
        private bool TryCorrectTimestamp(long prevFieldTimestamp, DateTime fieldToCorrectTimestamp, IVtiTimeStamp fieldToCorrect, int frameStep, int?aavIntegratedFields, bool isAav)
        {
            string dateFormatComp = fieldToCorrect.ContainsDate ? "yyyy-MM-dd HH:mm:ss.fff" : "HH:mm:ss.fff";

            double stepCorrection    = frameStep > 1 ? ((20000 * (frameStep - 1) * (m_VideoFormat == VideoFormat.PAL ? VtiTimeStampComposer.FIELD_DURATION_PAL : VtiTimeStampComposer.FIELD_DURATION_NTSC))) : 0;
            double fieldDistance     = (10000 * (m_VideoFormat == VideoFormat.PAL ? VtiTimeStampComposer.FIELD_DURATION_PAL : VtiTimeStampComposer.FIELD_DURATION_NTSC));
            double aavCorrection     = aavIntegratedFields.HasValue ? (10000 * (aavIntegratedFields.Value - 2) * (m_VideoFormat == VideoFormat.PAL ? VtiTimeStampComposer.FIELD_DURATION_PAL : VtiTimeStampComposer.FIELD_DURATION_NTSC)) : 0;
            long   expectedTimestamp =
                prevFieldTimestamp + (long)Math.Round(stepCorrection + fieldDistance + aavCorrection);

            // Round the expected timestamp to a millisecond
            expectedTimestamp = 10000L * ((long)Math.Round(expectedTimestamp / 10000.0));

            // NOTE: We ignore the last digit from the milliseconds when comparing this timestamps. While this allows for incorectly read 10th of milliseconds to be passed
            //       unactioned, it doesn't create any timing or measurement issues
            DateTime expectedDateTime          = new DateTime(expectedTimestamp);
            string   expectedTimestampString   = expectedDateTime.ToString(dateFormatComp);
            string   expectedTimestampStringM1 = expectedDateTime.AddMilliseconds(-1).ToString(dateFormatComp);
            string   expectedTimestampStringP1 = expectedDateTime.AddMilliseconds(1).ToString(dateFormatComp);
            string   actualTimestampString     = fieldToCorrectTimestamp.ToString(dateFormatComp);

            string difference          = XorStrings(expectedTimestampString, actualTimestampString);
            long   numberDifferences   = difference.ToCharArray().Count(c => c != '\0');
            string differenceM1        = XorStrings(expectedTimestampStringM1, actualTimestampString);
            long   numberDifferencesM1 = differenceM1.ToCharArray().Count(c => c != '\0');
            string differenceP1        = XorStrings(expectedTimestampStringP1, actualTimestampString);
            long   numberDifferencesP1 = differenceP1.ToCharArray().Count(c => c != '\0');

            if (numberDifferences < numberDifferencesM1 && numberDifferences < numberDifferencesP1)
            {
                // Already correct
            }
            else if (numberDifferencesM1 < numberDifferences && numberDifferencesM1 < numberDifferencesP1)
            {
                numberDifferences = numberDifferencesM1;
                expectedDateTime  = expectedDateTime.AddMilliseconds(-1);
            }
            else if (numberDifferencesP1 < numberDifferences && numberDifferencesP1 < numberDifferencesM1)
            {
                numberDifferences = numberDifferencesP1;
                expectedDateTime  = expectedDateTime.AddMilliseconds(1);
            }

            if (numberDifferences <= TangraConfig.Settings.Generic.OcrMaxNumberDigitsToAutoCorrect ||
                (isAav && fieldToCorrect.Milliseconds10 == 0) /* Duplicated video field in AAV */)
            {
                // We can correct the one or two offending characters

                if (fieldToCorrect.ContainsDate)
                {
                    fieldToCorrect.CorrectDate(expectedDateTime.Year, expectedDateTime.Month, expectedDateTime.Day);
                }

                fieldToCorrect.Correct(expectedDateTime.Hour, expectedDateTime.Minute, expectedDateTime.Second, (int)Math.Round((expectedDateTime.Ticks % 10000000) / 1000.0));
                fieldToCorrect.NumberOfCorrectedDifferences = (int)numberDifferences;
                return(true);
            }
            else
            {
                // Cannot correct more than one differences. Why not??
                return(false);
            }
        }
Exemple #12
0
        public bool TryToCorrect(int frameNo, int frameStep, int?aavIntegratedFields, IVtiTimeStamp oddFieldOSD, IVtiTimeStamp evenFieldOSD, bool evenBeforeOdd, ref DateTime oddFieldTimestamp, ref DateTime evenFieldTimestamp, out string correctionDebugInfo)
        {
            if (m_PrevFrameNo == -1 || m_PrevOddTicks == -1 || m_PrevEvenTicks == -1)
            {
                correctionDebugInfo = "Cannot correct. m_PrevFrameNo == -1 || m_PrevOddTicks == -1 || m_PrevEvenTicks == -1";
                return(false);
            }

            if (oddFieldOSD.ContainsDate)
            {
                correctionDebugInfo = string.Format("IOTA-VTI Correction Attempt for Frame {0}. {1:D4}-{2:D2}-{3:D2} {4:D2}:{5:D2}:{6:D2}.{7:D4} ({8}) - {9:D4}-{10:D2}-{11:D2} {12:D2}:{13:D2}:{14:D2}.{15:D4} ({16}). FrameStep: {17}. Previous: {18:D4}-{19:D2}-{20:D2} {21:D2}:{22:D2}:{23:D2}.{24:D4} ({25}) - {26:D4}-{27:D2}-{28:D2} {29:D2}:{30:D2}:{31:D2}.{32:D4} ({33})",
                                                    frameNo,
                                                    oddFieldOSD.Year, oddFieldOSD.Month, oddFieldOSD.Day, oddFieldOSD.Hours, oddFieldOSD.Minutes, oddFieldOSD.Seconds, oddFieldOSD.Milliseconds10, oddFieldOSD.FrameNumber,
                                                    evenFieldOSD.Year, evenFieldOSD.Month, evenFieldOSD.Day, evenFieldOSD.Hours, evenFieldOSD.Minutes, evenFieldOSD.Seconds, evenFieldOSD.Milliseconds10, evenFieldOSD.FrameNumber,
                                                    frameStep,
                                                    m_PrevOddFieldOSD.Year, m_PrevOddFieldOSD.Month, m_PrevOddFieldOSD.Day, m_PrevOddFieldOSD.Hours, m_PrevOddFieldOSD.Minutes, m_PrevOddFieldOSD.Seconds, m_PrevOddFieldOSD.Milliseconds10, m_PrevOddFieldNo,
                                                    m_PrevEvenFieldOSD.Year, m_PrevEvenFieldOSD.Month, m_PrevEvenFieldOSD.Day, m_PrevEvenFieldOSD.Hours, m_PrevEvenFieldOSD.Minutes, m_PrevEvenFieldOSD.Seconds, m_PrevEvenFieldOSD.Milliseconds10, m_PrevEvenFieldNo);
            }
            else
            {
                correctionDebugInfo = string.Format("IOTA-VTI Correction Attempt for Frame {0}. {1:D2}:{2:D2}:{3:D2}.{4:D4} ({5}) - {6:D2}:{7:D2}:{8:D2}.{9:D4} ({10}). FrameStep: {11}. Previous: {12:D2}:{13:D2}:{14:D2}.{15:D4} ({16}) - {17:D2}:{18:D2}:{19:D2}.{20:D4} ({21})",
                                                    frameNo,
                                                    oddFieldOSD.Hours, oddFieldOSD.Minutes, oddFieldOSD.Seconds, oddFieldOSD.Milliseconds10, oddFieldOSD.FrameNumber,
                                                    evenFieldOSD.Hours, evenFieldOSD.Minutes, evenFieldOSD.Seconds, evenFieldOSD.Milliseconds10, evenFieldOSD.FrameNumber,
                                                    frameStep,
                                                    m_PrevOddFieldOSD.Hours, m_PrevOddFieldOSD.Minutes, m_PrevOddFieldOSD.Seconds, m_PrevOddFieldOSD.Milliseconds10, m_PrevOddFieldNo,
                                                    m_PrevEvenFieldOSD.Hours, m_PrevEvenFieldOSD.Minutes, m_PrevEvenFieldOSD.Seconds, m_PrevEvenFieldOSD.Milliseconds10, m_PrevEvenFieldNo);
            }

            float knownFrameDuration = m_VideoFormat == VideoFormat.PAL
                        ? 2 * VtiTimeStampComposer.FIELD_DURATION_PAL
                        : 2 * VtiTimeStampComposer.FIELD_DURATION_NTSC;

            double fieldDuration;
            bool   returnBlank;
            bool   isDuplicateFrame = false;

            if (!evenBeforeOdd)
            {
                DateTime oddTimestampToCheck = oddFieldTimestamp;

                fieldDuration = Math.Abs(new TimeSpan(oddFieldTimestamp.Ticks - m_PrevEvenTicks).TotalMilliseconds) - (frameStep - 1) * knownFrameDuration;

                if (IsDuplicatedOrDroppedFrames(m_PrevOddFieldOSD, m_PrevEvenFieldOSD, oddFieldOSD, evenFieldOSD, frameStep, knownFrameDuration, aavIntegratedFields, out returnBlank))
                {
                    if (returnBlank)
                    {
                        // The Duplicate/Dropped frame engine decided it is safer to return a blank frame
                        return(false);
                    }
                    else
                    {
                        // Duplicate or dropped frame detected. No corrections requied.
                        isDuplicateFrame = true;
                    }
                }
                else
                {
                    if (!IsFieldDurationOkay(fieldDuration))
                    {
                        if (!TryCorrectTimestamp(m_PrevEvenTicks, oddFieldTimestamp, oddFieldOSD, frameStep, null, aavIntegratedFields != null))
                        {
                            Trace.WriteLine(correctionDebugInfo);
                            Trace.WriteLine("IOTA-VTI Correction Failed: Cannot correct field duration PrevEven -> CurrOdd.");
                            return(false);
                        }
                        else
                        {
                            if (oddFieldOSD.ContainsDate)
                            {
                                oddTimestampToCheck = new DateTime(oddFieldOSD.Year, oddFieldOSD.Month, oddFieldOSD.Day, oddFieldOSD.Hours, oddFieldOSD.Minutes, oddFieldOSD.Seconds).AddMilliseconds(Math.Min(10000, oddFieldOSD.Milliseconds10) / 10.0f);
                            }
                            else
                            {
                                oddTimestampToCheck = new DateTime(1, 1, 1, oddFieldOSD.Hours, oddFieldOSD.Minutes, oddFieldOSD.Seconds).AddMilliseconds(Math.Min(10000, oddFieldOSD.Milliseconds10) / 10.0f);
                            }
                        }
                    }

                    fieldDuration = Math.Abs(new TimeSpan(oddTimestampToCheck.Ticks - evenFieldTimestamp.Ticks).TotalMilliseconds);
                    if (aavIntegratedFields != null)
                    {
                        fieldDuration = fieldDuration / (aavIntegratedFields.Value - 1);
                    }

                    if (!IsFieldDurationOkay(fieldDuration))
                    {
                        if (!TryCorrectTimestamp(oddTimestampToCheck.Ticks, evenFieldTimestamp, evenFieldOSD, 1, aavIntegratedFields, aavIntegratedFields != null))
                        {
                            Trace.WriteLine(correctionDebugInfo);
                            Trace.WriteLine("IOTA-VTI Correction Failed: Cannot correct field duration CurrOdd -> CurrEven.");
                            return(false);
                        }
                    }
                }
            }
            else
            {
                DateTime evenTimestampToCheck = evenFieldTimestamp;

                fieldDuration = Math.Abs(new TimeSpan(evenFieldTimestamp.Ticks - m_PrevOddTicks).TotalMilliseconds) - (frameStep - 1) * knownFrameDuration;

                if (IsDuplicatedOrDroppedFrames(m_PrevEvenFieldOSD, m_PrevOddFieldOSD, evenFieldOSD, oddFieldOSD, frameStep, knownFrameDuration, aavIntegratedFields, out returnBlank))
                {
                    if (returnBlank)
                    {
                        // The Duplicate/Dropped frame engine decided it is safer to return a blank frame
                        return(false);
                    }
                    else
                    {
                        // Duplicate or dropped frame detected. No corrections requied.
                        isDuplicateFrame = true;
                    }
                }
                else
                {
                    if (!IsFieldDurationOkay(fieldDuration))
                    {
                        if (
                            !TryCorrectTimestamp(m_PrevOddTicks, evenFieldTimestamp, evenFieldOSD, frameStep, null,
                                                 aavIntegratedFields != null))
                        {
                            Trace.WriteLine(correctionDebugInfo);
                            Trace.WriteLine("IOTA-VTI Correction Failed: Cannot correct field duration PrevOdd -> CurrEven.");
                            return(false);
                        }
                        else
                        {
                            if (evenFieldOSD.ContainsDate)
                            {
                                evenTimestampToCheck = new DateTime(evenFieldOSD.Year, evenFieldOSD.Month, evenFieldOSD.Day, evenFieldOSD.Hours, evenFieldOSD.Minutes, evenFieldOSD.Seconds).AddMilliseconds(Math.Min(10000, evenFieldOSD.Milliseconds10) / 10.0f);
                            }
                            else
                            {
                                evenTimestampToCheck = new DateTime(1, 1, 1, evenFieldOSD.Hours, evenFieldOSD.Minutes, evenFieldOSD.Seconds).AddMilliseconds(Math.Min(10000, evenFieldOSD.Milliseconds10) / 10.0f);
                            }
                        }
                    }

                    fieldDuration = Math.Abs(new TimeSpan(evenTimestampToCheck.Ticks - oddFieldTimestamp.Ticks).TotalMilliseconds);
                    if (aavIntegratedFields != null)
                    {
                        fieldDuration = fieldDuration / (aavIntegratedFields.Value - 1);
                    }

                    if (!IsFieldDurationOkay(fieldDuration))
                    {
                        if (!TryCorrectTimestamp(evenTimestampToCheck.Ticks, oddFieldTimestamp, oddFieldOSD, 1, aavIntegratedFields, aavIntegratedFields != null))
                        {
                            Trace.WriteLine(correctionDebugInfo);
                            Trace.WriteLine("IOTA-VTI Correction Failed: Cannot correct field duration CurrEven -> CurrOdd.");
                            return(false);
                        }
                    }
                }
            }

            if (oddFieldOSD.ContainsFrameNumbers && !isDuplicateFrame)
            {
                var aavFrameNoCorr = aavIntegratedFields.HasValue ? (aavIntegratedFields.Value - 2) : 0;

                if (!evenBeforeOdd)
                {
                    if (m_PrevEvenFieldNo + 1 != oddFieldOSD.FrameNumber)
                    {
                        oddFieldOSD.CorrectFrameNumber((int)(m_PrevEvenFieldNo + 1));
                    }

                    if (oddFieldOSD.FrameNumber + 1 + aavFrameNoCorr != evenFieldOSD.FrameNumber)
                    {
                        evenFieldOSD.CorrectFrameNumber((int)(oddFieldOSD.FrameNumber + 1 + aavFrameNoCorr));
                    }
                }
                else
                {
                    if (m_PrevOddFieldNo + 1 != evenFieldOSD.FrameNumber)
                    {
                        evenFieldOSD.CorrectFrameNumber((int)(m_PrevOddFieldNo + 1));
                    }

                    if (evenFieldOSD.FrameNumber + 1 + aavFrameNoCorr != oddFieldOSD.FrameNumber)
                    {
                        oddFieldOSD.CorrectFrameNumber((int)(evenFieldOSD.FrameNumber + 1 + aavFrameNoCorr));
                    }
                }
            }

            if (oddFieldOSD.ContainsDate)
            {
                oddFieldTimestamp  = new DateTime(oddFieldOSD.Year, oddFieldOSD.Month, oddFieldOSD.Day, oddFieldOSD.Hours, oddFieldOSD.Minutes, oddFieldOSD.Seconds).AddMilliseconds(Math.Min(10000, oddFieldOSD.Milliseconds10) / 10.0f);
                evenFieldTimestamp = new DateTime(evenFieldOSD.Year, evenFieldOSD.Month, evenFieldOSD.Day, evenFieldOSD.Hours, evenFieldOSD.Minutes, evenFieldOSD.Seconds).AddMilliseconds(Math.Min(10000, evenFieldOSD.Milliseconds10) / 10.0f);
            }
            else
            {
                oddFieldTimestamp  = new DateTime(1, 1, 1, oddFieldOSD.Hours, oddFieldOSD.Minutes, oddFieldOSD.Seconds).AddMilliseconds(Math.Min(10000, oddFieldOSD.Milliseconds10) / 10.0f);
                evenFieldTimestamp = new DateTime(1, 1, 1, evenFieldOSD.Hours, evenFieldOSD.Minutes, evenFieldOSD.Seconds).AddMilliseconds(Math.Min(10000, evenFieldOSD.Milliseconds10) / 10.0f);
            }

            return(true);
        }
Exemple #13
0
        // Note this method only looks at exact duplicate or dropped frames, assuming that all timestamp digits have been recognized correctly
        // It is also looking for exactly one single dropped frame
        private bool IsDuplicatedOrDroppedFrames(IVtiTimeStamp prefFrameField1, IVtiTimeStamp prefFrameField2, IVtiTimeStamp field1, IVtiTimeStamp field2, int frameStep, float knownFrameDurationMS, int?aavIntegratedFields, out bool returnBlank)
        {
            // The main challenge here is to correctly identify duplicate/dropped frames and not miss-identify OCR errors
            // that could accidentaly make the extracted time look like there was a duplicate/dropped frame
            // For this reason we require matching in both timestamps and field numbers (if field numbers are supported)
            if (prefFrameField1.HoursMinSecMilliEquals(field1) && prefFrameField2.HoursMinSecMilliEquals(field2))
            {
                Trace.WriteLine(string.Format("{0} {1} {2} {3}", prefFrameField1.AsString(), prefFrameField2.AsString(), field1.AsString(), field2.AsString()));

                if (prefFrameField1.ContainsFrameNumbers && field1.ContainsFrameNumbers)
                {
                    if (prefFrameField1.FrameNumber == field1.FrameNumber || prefFrameField2.FrameNumber == field2.FrameNumber)
                    {
                        Trace.WriteLine("OCR engine identifies duplicated frame.");
                        returnBlank = false;
                        return(true);
                    }
                    else
                    {
                        Trace.WriteLine("OCR engine decided to return a blank timestamp while identifying duplicated frame.");
                        returnBlank = true;
                        return(true);
                    }
                }
                else
                {
                    Trace.WriteLine("OCR engine identifies duplicated frame. Frame numbers are not supported.");
                    returnBlank = false;
                    return(true);
                }
            }

            var newField1Ticks             = field1.GetTicks();
            var droppedField1ExpectedTicks = new DateTime(prefFrameField1.GetTicks()).AddMilliseconds((frameStep + 1) * knownFrameDurationMS).Ticks;
            var newField2Ticks             = field2.GetTicks();
            var droppedField2ExpectedTicks = new DateTime(prefFrameField2.GetTicks()).AddMilliseconds((frameStep + 1) * knownFrameDurationMS).Ticks;

            if (Math.Abs(new TimeSpan(droppedField1ExpectedTicks - newField1Ticks).TotalMilliseconds) < 2 && Math.Abs(new TimeSpan(droppedField2ExpectedTicks - newField2Ticks).TotalMilliseconds) < 2)
            {
                if (prefFrameField1.ContainsFrameNumbers && field1.ContainsFrameNumbers)
                {
                    if (prefFrameField1.FrameNumber + (frameStep + 1) * 2 == field1.FrameNumber || prefFrameField2.FrameNumber + (frameStep + 1) * 2 == field2.FrameNumber)
                    {
                        Trace.WriteLine("OCR engine identifies dropped frame.");
                        returnBlank = false;
                        return(true);
                    }
                    else
                    {
                        Trace.WriteLine("OCR engine decided to return a blank timestamp while identifying dropped frame.");
                        returnBlank = true;
                        return(true);
                    }
                }
                else
                {
                    Trace.WriteLine("OCR engine identifies dropped frame. Frame numbers are not supported.");
                    returnBlank = false;
                    return(true);
                }
            }

            returnBlank = false;
            return(false);
        }
Exemple #14
0
        public bool TryToCorrectDuplicateField(int frameNo, int frameStep, IVtiTimeStamp oddFieldOSD, IVtiTimeStamp evenFieldOSD, ref DateTime frameTimestamp, out string correctionDebugInfo)
        {
            if (m_PrevFrameNo == -1 || m_PrevOddTicks == -1 || m_PrevEvenTicks == -1)
            {
                correctionDebugInfo = "Cannot correct. m_PrevFrameNo == -1 || m_PrevOddTicks == -1 || m_PrevEvenTicks == -1";
                return(false);
            }

            if (oddFieldOSD.ContainsDate)
            {
                correctionDebugInfo = string.Format("IOTA-VTI Correction Attempt for Frame {0}. {1:D4}-{2:D2}-{3:D2} {4:D2}:{5:D2}:{6:D2}.{7:D4} ({8}) - {9:D4}-{10:D2}-{11:D2} {12:D2}:{13:D2}:{14:D2}.{15:D4} ({16}). FrameStep: {17}. Previous: {18:D4}-{19:D2}-{20:D2} {21:D2}:{22:D2}:{23:D2}.{24:D4} ({25}) - {26:D4}-{27:D2}-{28:D2} {29:D2}:{30:D2}:{31:D2}.{32:D4} ({33})",
                                                    frameNo,
                                                    oddFieldOSD.Year, oddFieldOSD.Month, oddFieldOSD.Day, oddFieldOSD.Hours, oddFieldOSD.Minutes, oddFieldOSD.Seconds, oddFieldOSD.Milliseconds10, oddFieldOSD.FrameNumber,
                                                    evenFieldOSD.Year, evenFieldOSD.Month, evenFieldOSD.Day, evenFieldOSD.Hours, evenFieldOSD.Minutes, evenFieldOSD.Seconds, evenFieldOSD.Milliseconds10, evenFieldOSD.FrameNumber,
                                                    frameStep,
                                                    m_PrevOddFieldOSD.Year, m_PrevOddFieldOSD.Month, m_PrevOddFieldOSD.Day, m_PrevOddFieldOSD.Hours, m_PrevOddFieldOSD.Minutes, m_PrevOddFieldOSD.Seconds, m_PrevOddFieldOSD.Milliseconds10, m_PrevOddFieldNo,
                                                    m_PrevEvenFieldOSD.Year, m_PrevEvenFieldOSD.Month, m_PrevEvenFieldOSD.Day, m_PrevEvenFieldOSD.Hours, m_PrevEvenFieldOSD.Minutes, m_PrevEvenFieldOSD.Seconds, m_PrevEvenFieldOSD.Milliseconds10, m_PrevEvenFieldNo);
            }
            else
            {
                correctionDebugInfo = string.Format("IOTA-VTI Correction Attempt for Frame {0}. {1:D2}:{2:D2}:{3:D2}.{4:D4} ({5}) - {6:D2}:{7:D2}:{8:D2}.{9:D4} ({10}). FrameStep: {11}. Previous: {12:D2}:{13:D2}:{14:D2}.{15:D4} ({16}) - {17:D2}:{18:D2}:{19:D2}.{20:D4} ({21})",
                                                    frameNo,
                                                    oddFieldOSD.Hours, oddFieldOSD.Minutes, oddFieldOSD.Seconds, oddFieldOSD.Milliseconds10, oddFieldOSD.FrameNumber,
                                                    evenFieldOSD.Hours, evenFieldOSD.Minutes, evenFieldOSD.Seconds, evenFieldOSD.Milliseconds10, evenFieldOSD.FrameNumber,
                                                    frameStep,
                                                    m_PrevOddFieldOSD.Hours, m_PrevOddFieldOSD.Minutes, m_PrevOddFieldOSD.Seconds, m_PrevOddFieldOSD.Milliseconds10, m_PrevOddFieldNo,
                                                    m_PrevEvenFieldOSD.Hours, m_PrevEvenFieldOSD.Minutes, m_PrevEvenFieldOSD.Seconds, m_PrevEvenFieldOSD.Milliseconds10, m_PrevEvenFieldNo);
            }

            float knownFrameDuration = m_VideoFormat == VideoFormat.PAL
                        ? 2 * VtiTimeStampComposer.FIELD_DURATION_PAL
                        : 2 * VtiTimeStampComposer.FIELD_DURATION_NTSC;

            var fieldDuration = Math.Abs(new TimeSpan(frameTimestamp.Ticks - m_PrevEvenTicks).TotalMilliseconds / 2.0) - (frameStep - 1) * knownFrameDuration;

            bool returnBlank;

            if (IsDuplicatedOrDroppedFrames(m_PrevOddFieldOSD, m_PrevEvenFieldOSD, oddFieldOSD, evenFieldOSD, frameStep, knownFrameDuration, null, out returnBlank))
            {
                if (returnBlank)
                {
                    // The Duplicate/Dropped frame engine decided it is safer to return a blank frame
                    return(false);
                }
                else
                {
                    // Duplicate or dropped frame detected. No corrections requied.
                }
            }
            else
            {
                if (!IsFieldDurationOkay(fieldDuration))
                {
                    long fieldDistance = (long)Math.Round((10000 * (m_VideoFormat == VideoFormat.PAL ? VtiTimeStampComposer.FIELD_DURATION_PAL : VtiTimeStampComposer.FIELD_DURATION_NTSC)));

                    if (!TryCorrectTimestamp(m_PrevOddTicks + fieldDistance, frameTimestamp, oddFieldOSD, frameStep, null, false))
                    {
                        Trace.WriteLine(correctionDebugInfo);
                        Trace.WriteLine("IOTA-VTI Correction Failed: Cannot correct field duration PrevEven -> CurrOdd.");
                        return(false);
                    }
                }
            }

            if (oddFieldOSD.ContainsDate)
            {
                frameTimestamp = new DateTime(oddFieldOSD.Year, oddFieldOSD.Month, oddFieldOSD.Day, oddFieldOSD.Hours, oddFieldOSD.Minutes, oddFieldOSD.Seconds).AddMilliseconds(Math.Min(10000, oddFieldOSD.Milliseconds10) / 10.0f);
            }
            else
            {
                frameTimestamp = new DateTime(1, 1, 1, oddFieldOSD.Hours, oddFieldOSD.Minutes, oddFieldOSD.Seconds).AddMilliseconds(Math.Min(10000, oddFieldOSD.Milliseconds10) / 10.0f);
            }

            return(true);
        }