1 /***************************************************************************
2     copyright            : (C) 2017 by mean
3     email                : fixounet@free.fr
4  ***************************************************************************/
5 
6 /***************************************************************************
7  *                                                                         *
8  *   This program is free software; you can redistribute it and/or modify  *
9  *   it under the terms of the GNU General Public License as published by  *
10  *   the Free Software Foundation; either version 2 of the License, or     *
11  *   (at your option) any later version.                                   *
12  *                                                                         *
13  ***************************************************************************/
14 #include "ADM_cpp.h"
15 #include <math.h>
16 #include <stdlib.h>
17 #include "ADM_default.h"
18 
19 #include "ADM_mkvDeviation.h"
20 
21 
mkvDeviation(int n)22 mkvDeviation::mkvDeviation(int n)
23 {
24     total=n;
25     nbValid=0;
26     sorted=new uint64_t[n];
27 }
~mkvDeviation()28 mkvDeviation::~mkvDeviation()
29 {
30     delete [] sorted;
31     sorted=NULL;
32 }
33 
comp64_t(const void * elem1,const void * elem2)34 static int comp64_t (const void * elem1, const void * elem2)
35 {
36     uint64_t left=*(uint64_t *)elem1;
37     uint64_t right=*(uint64_t *)elem2;
38     if(left==right) return 0;
39     if(left>right) return 1;
40     return -1;
41 }
sort()42 void mkvDeviation::sort()
43 {
44     qsort(sorted,nbValid,sizeof(uint64_t),comp64_t);
45 }
46 
47 
48 
49 /**
50     \fn computeDeviation
51     \brief returns the # of errors when forcing timestamp to be num/den (interval in us)
52       num=1000
53       den=24000 for a 24 fps
54 
55 
56 */
computeDeviation(int num,int den,int & nbSkipped)57 int mkvDeviation::computeDeviation(int num, int den,int &nbSkipped)
58 {
59   double dHalf=(500000.*(double)num)/((double)den);
60   int half=dHalf-1; // half interval in us
61   double sumOfError=0;
62   // Sorted contains the sorted list of valid PTS
63   double coeff=(double)num*1000000.;
64   coeff=coeff/(double)den;
65   int multipleError=0;
66   int lastValidFrame=1;
67 
68   int multipleCount=5;
69   int maxDelta=0;
70   int minDelta=8*1000 *1000;
71   nbSkipped=0;
72 
73   for(int i=1;i<nbValid;i++)
74   {
75       int delta=(int)(sorted[i]-sorted[i-1]);
76       if(delta>maxDelta) maxDelta=delta;
77       if(delta<minDelta) minDelta=delta;
78       if(sorted[i]<=sorted[i-1])
79           ADM_warning("Sorting error : [%d] %lld : %lld\n",i,sorted[i],sorted[i-1]);
80 
81   }
82 
83 
84   for(int i=2;i<nbValid;i++) // skip the 2 first frames, often wrong
85   {
86     uint64_t pts=sorted[i];
87     double dmultiple=(pts+half);
88     dmultiple/=coeff;
89     uint64_t multiple=(uint64_t)dmultiple;
90     double reconstructed=(double)multiple*coeff;
91     double deviation=(double)fabs((double)pts-reconstructed);
92 
93     if(multiple<=lastValidFrame )
94     {
95      //   printf("Warning : Multiple match for the same number (%d)\n",multiple);
96         sumOfError+=coeff*coeff; // full frame error
97         multipleError++;
98         if(multipleCount)
99         {
100             multipleCount--;
101             printf("Frame %d, multiple = %d\n",i,multiple);
102         }
103         continue;
104     }
105     int jump=(multiple-lastValidFrame)-1;
106     if(jump)
107     {
108         //printf("Skipped %d %d\n",i,jump);
109         nbSkipped+=jump;
110         //sumOfError=sumOfError+(1+jump)*(1+jump)*coeff*coeff;
111         lastValidFrame=multiple;
112         continue;
113     }
114     lastValidFrame=multiple;
115     //printf("frame %d multiple = %d, deviation=%d\n",i,(int)multiple,(int)deviation);
116 
117     // We have an accuracy of 1ms, so if the error is less than 2 ms, we ignore it
118     if(deviation>2000.)
119     {
120         int dev=(int)deviation;
121         dev=dev-dev%1000;
122         deviation=dev;
123         sumOfError=sumOfError+(deviation*deviation);
124     }
125   }
126 
127   sumOfError/=(double)nbValid;
128   sumOfError=sqrt(sumOfError);
129   ADM_info("Den=%d Num=%d  sum of error=%d, multiple=%d\n",den,num,(int)sumOfError,multipleError);
130   ADM_info("MinDelta=%d maxDelta=%d skipped=%d\n",minDelta,maxDelta,nbSkipped);
131   return (int)sumOfError  ;
132 }
133