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