FFmpeg
signature_lookup.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017 Gerion Entrup
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with FFmpeg; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20 
21 /**
22  * @file
23  * MPEG-7 video signature calculation and lookup filter
24  */
25 
26 #include "signature.h"
27 
28 #define HOUGH_MAX_OFFSET 90
29 #define MAX_FRAMERATE 60
30 
31 #define DIR_PREV 0
32 #define DIR_NEXT 1
33 #define DIR_PREV_END 2
34 #define DIR_NEXT_END 3
35 
36 #define STATUS_NULL 0
37 #define STATUS_END_REACHED 1
38 #define STATUS_BEGIN_REACHED 2
39 
40 static void fill_l1distlut(uint8_t lut[])
41 {
42  int i, j, tmp_i, tmp_j,count;
43  uint8_t dist;
44 
45  for (i = 0, count = 0; i < 242; i++) {
46  for (j = i + 1; j < 243; j++, count++) {
47  /* ternary distance between i and j */
48  dist = 0;
49  tmp_i = i; tmp_j = j;
50  do {
51  dist += FFABS((tmp_j % 3) - (tmp_i % 3));
52  tmp_j /= 3;
53  tmp_i /= 3;
54  } while (tmp_i > 0 || tmp_j > 0);
55  lut[count] = dist;
56  }
57  }
58 }
59 
60 static unsigned int intersection_word(const uint8_t *first, const uint8_t *second)
61 {
62  unsigned int val=0,i;
63  for (i = 0; i < 28; i += 4) {
64  val += av_popcount( (first[i] & second[i] ) << 24 |
65  (first[i+1] & second[i+1]) << 16 |
66  (first[i+2] & second[i+2]) << 8 |
67  (first[i+3] & second[i+3]) );
68  }
69  val += av_popcount( (first[28] & second[28]) << 16 |
70  (first[29] & second[29]) << 8 |
71  (first[30] & second[30]) );
72  return val;
73 }
74 
75 static unsigned int union_word(const uint8_t *first, const uint8_t *second)
76 {
77  unsigned int val=0,i;
78  for (i = 0; i < 28; i += 4) {
79  val += av_popcount( (first[i] | second[i] ) << 24 |
80  (first[i+1] | second[i+1]) << 16 |
81  (first[i+2] | second[i+2]) << 8 |
82  (first[i+3] | second[i+3]) );
83  }
84  val += av_popcount( (first[28] | second[28]) << 16 |
85  (first[29] | second[29]) << 8 |
86  (first[30] | second[30]) );
87  return val;
88 }
89 
90 static unsigned int get_l1dist(AVFilterContext *ctx, SignatureContext *sc, const uint8_t *first, const uint8_t *second)
91 {
92  unsigned int i;
93  unsigned int dist = 0;
94  uint8_t f, s;
95 
96  for (i = 0; i < SIGELEM_SIZE/5; i++) {
97  if (first[i] != second[i]) {
98  f = first[i];
99  s = second[i];
100  if (f > s) {
101  /* little variation of gauss sum formula */
102  dist += sc->l1distlut[243*242/2 - (243-s)*(242-s)/2 + f - s - 1];
103  } else {
104  dist += sc->l1distlut[243*242/2 - (243-f)*(242-f)/2 + s - f - 1];
105  }
106  }
107  }
108  return dist;
109 }
110 
111 /**
112  * calculates the jaccard distance and evaluates a pair of coarse signatures as good
113  * @return 0 if pair is bad, 1 otherwise
114  */
116 {
117  int jaccarddist, i, composdist = 0, cwthcount = 0;
118  for (i = 0; i < 5; i++) {
119  if ((jaccarddist = intersection_word(first->data[i], second->data[i])) > 0) {
120  jaccarddist /= union_word(first->data[i], second->data[i]);
121  }
122  if (jaccarddist >= sc->thworddist) {
123  if (++cwthcount > 2) {
124  /* more than half (5/2) of distances are too wide */
125  return 0;
126  }
127  }
128  composdist += jaccarddist;
129  if (composdist > sc->thcomposdist) {
130  return 0;
131  }
132  }
133  return 1;
134 }
135 
136 /**
137  * step through the coarsesignatures as long as a good candidate is found
138  * @return 0 if no candidate is found, 1 otherwise
139  */
141 {
142  /* go one coarsesignature foreword */
143  if (!start) {
144  if ((*second)->next) {
145  *second = (*second)->next;
146  } else if ((*first)->next) {
147  *second = secondstart;
148  *first = (*first)->next;
149  } else {
150  return 0;
151  }
152  }
153 
154  while (1) {
155  if (get_jaccarddist(sc, *first, *second))
156  return 1;
157 
158  /* next signature */
159  if ((*second)->next) {
160  *second = (*second)->next;
161  } else if ((*first)->next) {
162  *second = secondstart;
163  *first = (*first)->next;
164  } else {
165  return 0;
166  }
167  }
168 }
169 
170 /**
171  * compares framesignatures and sorts out signatures with a l1 distance above a given threshold.
172  * Then tries to find out offset and differences between framerates with a hough transformation
173  */
175 {
176  FineSignature *f, *s;
177  size_t i, j, k, l, hmax = 0, score;
178  int framerate, offset, l1dist;
179  double m;
180  MatchingInfo *cands = NULL, *c = NULL;
181 
182  struct {
183  uint8_t size;
184  unsigned int dist;
185  FineSignature *a;
186  uint8_t b_pos[COARSE_SIZE];
188  } pairs[COARSE_SIZE];
189 
190  typedef struct hspace_elem {
191  int dist;
192  size_t score;
193  FineSignature *a;
194  FineSignature *b;
195  } hspace_elem;
196 
197  /* houghspace */
198  hspace_elem** hspace = av_malloc_array(MAX_FRAMERATE, sizeof(hspace_elem *));
199 
200  /* initialize houghspace */
201  for (i = 0; i < MAX_FRAMERATE; i++) {
202  hspace[i] = av_malloc_array(2 * HOUGH_MAX_OFFSET + 1, sizeof(hspace_elem));
203  for (j = 0; j < 2 * HOUGH_MAX_OFFSET + 1; j++) {
204  hspace[i][j].score = 0;
205  hspace[i][j].dist = 99999;
206  }
207  }
208 
209  /* l1 distances */
210  for (i = 0, f = first; i < COARSE_SIZE && f->next; i++, f = f->next) {
211  pairs[i].size = 0;
212  pairs[i].dist = 99999;
213  pairs[i].a = f;
214  for (j = 0, s = second; j < COARSE_SIZE && s->next; j++, s = s->next) {
215  /* l1 distance of finesignature */
216  l1dist = get_l1dist(ctx, sc, f->framesig, s->framesig);
217  if (l1dist < sc->thl1) {
218  if (l1dist < pairs[i].dist) {
219  pairs[i].size = 1;
220  pairs[i].dist = l1dist;
221  pairs[i].b_pos[0] = j;
222  pairs[i].b[0] = s;
223  } else if (l1dist == pairs[i].dist) {
224  pairs[i].b[pairs[i].size] = s;
225  pairs[i].b_pos[pairs[i].size] = j;
226  pairs[i].size++;
227  }
228  }
229  }
230  }
231  /* last incomplete coarsesignature */
232  if (f->next == NULL) {
233  for (; i < COARSE_SIZE; i++) {
234  pairs[i].size = 0;
235  pairs[i].dist = 99999;
236  }
237  }
238 
239  /* hough transformation */
240  for (i = 0; i < COARSE_SIZE; i++) {
241  for (j = 0; j < pairs[i].size; j++) {
242  for (k = i + 1; k < COARSE_SIZE; k++) {
243  for (l = 0; l < pairs[k].size; l++) {
244  if (pairs[i].b[j] != pairs[k].b[l]) {
245  /* linear regression */
246  m = (pairs[k].b_pos[l]-pairs[i].b_pos[j]) / (k-i); /* good value between 0.0 - 2.0 */
247  framerate = (int) (m*30 + 0.5); /* round up to 0 - 60 */
248  if (framerate>0 && framerate <= MAX_FRAMERATE) {
249  offset = pairs[i].b_pos[j] - ((int) (m*i + 0.5)); /* only second part has to be rounded up */
251  if (pairs[i].dist < pairs[k].dist) {
252  if (pairs[i].dist < hspace[framerate-1][offset+HOUGH_MAX_OFFSET].dist) {
253  hspace[framerate-1][offset+HOUGH_MAX_OFFSET].dist = pairs[i].dist;
254  hspace[framerate-1][offset+HOUGH_MAX_OFFSET].a = pairs[i].a;
255  hspace[framerate-1][offset+HOUGH_MAX_OFFSET].b = pairs[i].b[j];
256  }
257  } else {
258  if (pairs[k].dist < hspace[framerate-1][offset+HOUGH_MAX_OFFSET].dist) {
259  hspace[framerate-1][offset+HOUGH_MAX_OFFSET].dist = pairs[k].dist;
260  hspace[framerate-1][offset+HOUGH_MAX_OFFSET].a = pairs[k].a;
261  hspace[framerate-1][offset+HOUGH_MAX_OFFSET].b = pairs[k].b[l];
262  }
263  }
264 
265  score = hspace[framerate-1][offset+HOUGH_MAX_OFFSET].score + 1;
266  if (score > hmax )
267  hmax = score;
268  hspace[framerate-1][offset+HOUGH_MAX_OFFSET].score = score;
269  }
270  }
271  }
272  }
273  }
274  }
275  }
276 
277  if (hmax > 0) {
278  hmax = (int) (0.7*hmax);
279  for (i = 0; i < MAX_FRAMERATE; i++) {
280  for (j = 0; j < HOUGH_MAX_OFFSET; j++) {
281  if (hmax < hspace[i][j].score) {
282  if (c == NULL) {
283  c = av_malloc(sizeof(MatchingInfo));
284  if (!c)
285  av_log(ctx, AV_LOG_FATAL, "Could not allocate memory");
286  cands = c;
287  } else {
288  c->next = av_malloc(sizeof(MatchingInfo));
289  if (!c->next)
290  av_log(ctx, AV_LOG_FATAL, "Could not allocate memory");
291  c = c->next;
292  }
293  c->framerateratio = (i+1.0) / 30;
294  c->score = hspace[i][j].score;
295  c->offset = j-90;
296  c->first = hspace[i][j].a;
297  c->second = hspace[i][j].b;
298  c->next = NULL;
299 
300  /* not used */
301  c->meandist = 0;
302  c->matchframes = 0;
303  c->whole = 0;
304  }
305  }
306  }
307  }
308  for (i = 0; i < MAX_FRAMERATE; i++) {
309  av_freep(&hspace[i]);
310  }
311  av_freep(&hspace);
312  return cands;
313 }
314 
315 static int iterate_frame(double frr, FineSignature **a, FineSignature **b, int fcount, int *bcount, int dir)
316 {
317  int step;
318 
319  /* between 1 and 2, because frr is between 1 and 2 */
320  step = ((int) 0.5 + fcount * frr) /* current frame */
321  -((int) 0.5 + (fcount-1) * frr);/* last frame */
322 
323  if (dir == DIR_NEXT) {
324  if (frr >= 1.0) {
325  if ((*a)->next) {
326  *a = (*a)->next;
327  } else {
328  return DIR_NEXT_END;
329  }
330 
331  if (step == 1) {
332  if ((*b)->next) {
333  *b = (*b)->next;
334  (*bcount)++;
335  } else {
336  return DIR_NEXT_END;
337  }
338  } else {
339  if ((*b)->next && (*b)->next->next) {
340  *b = (*b)->next->next;
341  (*bcount)++;
342  } else {
343  return DIR_NEXT_END;
344  }
345  }
346  } else {
347  if ((*b)->next) {
348  *b = (*b)->next;
349  (*bcount)++;
350  } else {
351  return DIR_NEXT_END;
352  }
353 
354  if (step == 1) {
355  if ((*a)->next) {
356  *a = (*a)->next;
357  } else {
358  return DIR_NEXT_END;
359  }
360  } else {
361  if ((*a)->next && (*a)->next->next) {
362  *a = (*a)->next->next;
363  } else {
364  return DIR_NEXT_END;
365  }
366  }
367  }
368  return DIR_NEXT;
369  } else {
370  if (frr >= 1.0) {
371  if ((*a)->prev) {
372  *a = (*a)->prev;
373  } else {
374  return DIR_PREV_END;
375  }
376 
377  if (step == 1) {
378  if ((*b)->prev) {
379  *b = (*b)->prev;
380  (*bcount)++;
381  } else {
382  return DIR_PREV_END;
383  }
384  } else {
385  if ((*b)->prev && (*b)->prev->prev) {
386  *b = (*b)->prev->prev;
387  (*bcount)++;
388  } else {
389  return DIR_PREV_END;
390  }
391  }
392  } else {
393  if ((*b)->prev) {
394  *b = (*b)->prev;
395  (*bcount)++;
396  } else {
397  return DIR_PREV_END;
398  }
399 
400  if (step == 1) {
401  if ((*a)->prev) {
402  *a = (*a)->prev;
403  } else {
404  return DIR_PREV_END;
405  }
406  } else {
407  if ((*a)->prev && (*a)->prev->prev) {
408  *a = (*a)->prev->prev;
409  } else {
410  return DIR_PREV_END;
411  }
412  }
413  }
414  return DIR_PREV;
415  }
416 }
417 
419 {
420  int dist, distsum = 0, bcount = 1, dir = DIR_NEXT;
421  int fcount = 0, goodfcount = 0, gooda = 0, goodb = 0;
422  double meandist, minmeandist = bestmatch.meandist;
423  int tolerancecount = 0;
424  FineSignature *a, *b, *aprev, *bprev;
425  int status = STATUS_NULL;
426 
427  for (; infos != NULL; infos = infos->next) {
428  a = infos->first;
429  b = infos->second;
430  while (1) {
431  dist = get_l1dist(ctx, sc, a->framesig, b->framesig);
432 
433  if (dist > sc->thl1) {
434  if (a->confidence >= 1 || b->confidence >= 1) {
435  /* bad frame (because high different information) */
436  tolerancecount++;
437  }
438 
439  if (tolerancecount > 2) {
440  a = aprev;
441  b = bprev;
442  if (dir == DIR_NEXT) {
443  /* turn around */
444  a = infos->first;
445  b = infos->second;
446  dir = DIR_PREV;
447  } else {
448  break;
449  }
450  }
451  } else {
452  /* good frame */
453  distsum += dist;
454  goodfcount++;
455  tolerancecount=0;
456 
457  aprev = a;
458  bprev = b;
459 
460  if (a->confidence < 1) gooda++;
461  if (b->confidence < 1) goodb++;
462  }
463 
464  fcount++;
465 
466  dir = iterate_frame(infos->framerateratio, &a, &b, fcount, &bcount, dir);
467  if (dir == DIR_NEXT_END) {
469  a = infos->first;
470  b = infos->second;
471  dir = iterate_frame(infos->framerateratio, &a, &b, fcount, &bcount, DIR_PREV);
472  }
473 
474  if (dir == DIR_PREV_END) {
476  break;
477  }
478 
479  if (sc->thdi != 0 && bcount >= sc->thdi) {
480  break; /* enough frames found */
481  }
482  }
483 
484  if (bcount < sc->thdi)
485  continue; /* matching sequence is too short */
486  if ((double) goodfcount / (double) fcount < sc->thit)
487  continue;
488  if ((double) goodfcount*0.5 < FFMAX(gooda, goodb))
489  continue;
490 
491  meandist = (double) goodfcount / (double) distsum;
492 
493  if (meandist < minmeandist ||
495  mode == MODE_FAST){
496  minmeandist = meandist;
497  /* bestcandidate in this iteration */
498  bestmatch.meandist = meandist;
499  bestmatch.matchframes = bcount;
500  bestmatch.framerateratio = infos->framerateratio;
501  bestmatch.score = infos->score;
502  bestmatch.offset = infos->offset;
503  bestmatch.first = infos->first;
504  bestmatch.second = infos->second;
505  bestmatch.whole = 0; /* will be set to true later */
506  bestmatch.next = NULL;
507  }
508 
509  /* whole sequence is automatically best match */
511  bestmatch.whole = 1;
512  break;
513  }
514 
515  /* first matching sequence is enough, finding the best one is not necessary */
516  if (mode == MODE_FAST) {
517  break;
518  }
519  }
520  return bestmatch;
521 }
522 
523 static void sll_free(MatchingInfo *sll)
524 {
525  void *tmp;
526  while (sll) {
527  tmp = sll;
528  sll = sll->next;
529  av_freep(&tmp);
530  }
531 }
532 
534 {
535  CoarseSignature *cs, *cs2;
536  MatchingInfo *infos;
537  MatchingInfo bestmatch;
538  MatchingInfo *i;
539 
540  cs = first->coarsesiglist;
541  cs2 = second->coarsesiglist;
542 
543  /* score of bestmatch is 0, if no match is found */
544  bestmatch.score = 0;
545  bestmatch.meandist = 99999;
546  bestmatch.whole = 0;
547 
549 
550  /* stage 1: coarsesignature matching */
551  if (find_next_coarsecandidate(sc, second->coarsesiglist, &cs, &cs2, 1) == 0)
552  return bestmatch; /* no candidate found */
553  do {
554  av_log(ctx, AV_LOG_DEBUG, "Stage 1: got coarsesignature pair. "
555  "indices of first frame: %"PRIu32" and %"PRIu32"\n",
556  cs->first->index, cs2->first->index);
557  /* stage 2: l1-distance and hough-transform */
558  av_log(ctx, AV_LOG_DEBUG, "Stage 2: calculate matching parameters\n");
559  infos = get_matching_parameters(ctx, sc, cs->first, cs2->first);
560  if (av_log_get_level() == AV_LOG_DEBUG) {
561  for (i = infos; i != NULL; i = i->next) {
562  av_log(ctx, AV_LOG_DEBUG, "Stage 2: matching pair at %"PRIu32" and %"PRIu32", "
563  "ratio %f, offset %d\n", i->first->index, i->second->index,
564  i->framerateratio, i->offset);
565  }
566  }
567  /* stage 3: evaluation */
568  av_log(ctx, AV_LOG_DEBUG, "Stage 3: evaluate\n");
569  if (infos) {
570  bestmatch = evaluate_parameters(ctx, sc, infos, bestmatch, mode);
571  av_log(ctx, AV_LOG_DEBUG, "Stage 3: best matching pair at %"PRIu32" and %"PRIu32", "
572  "ratio %f, offset %d, score %d, %d frames matching\n",
573  bestmatch.first->index, bestmatch.second->index,
574  bestmatch.framerateratio, bestmatch.offset, bestmatch.score, bestmatch.matchframes);
575  sll_free(infos);
576  }
577  } while (find_next_coarsecandidate(sc, second->coarsesiglist, &cs, &cs2, 0) && !bestmatch.whole);
578  return bestmatch;
579 
580 }
status
they must not be accessed directly The fifo field contains the frames that are queued in the input for processing by the filter The status_in and status_out fields contains the queued status(EOF or error) of the link
MatchingInfo::framerateratio
double framerateratio
Definition: signature.h:92
MAX_FRAMERATE
#define MAX_FRAMERATE
Definition: signature_lookup.c:29
StreamContext::coarsesiglist
CoarseSignature * coarsesiglist
Definition: signature.h:114
MatchingInfo::meandist
double meandist
Definition: signature.h:91
MatchingInfo
Definition: signature.h:90
tmp
static uint8_t tmp[11]
Definition: aes_ctr.c:28
step
trying all byte sequences megabyte in length and selecting the best looking sequence will yield cases to try But a word about which is also called distortion Distortion can be quantified by almost any quality measurement one chooses the sum of squared differences is used but more complex methods that consider psychovisual effects can be used as well It makes no difference in this discussion First step
Definition: rate_distortion.txt:58
COARSE_SIZE
#define COARSE_SIZE
Definition: signature.h:39
MatchingInfo::whole
int whole
Definition: signature.h:96
b
#define b
Definition: input.c:34
MatchingInfo::score
int score
Definition: signature.h:93
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
av_popcount
#define av_popcount
Definition: common.h:149
SignatureContext::l1distlut
uint8_t l1distlut[243 *242/2]
Definition: signature.h:141
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:30
framerate
int framerate
Definition: h264_levels.c:65
FineSignature::index
uint32_t index
Definition: signature.h:76
fill_l1distlut
static void fill_l1distlut(uint8_t lut[])
Definition: signature_lookup.c:40
lookup_signatures
static MatchingInfo lookup_signatures(AVFilterContext *ctx, SignatureContext *sc, StreamContext *first, StreamContext *second, int mode)
Definition: signature_lookup.c:533
val
static double val(void *priv, double ch)
Definition: aeval.c:77
SignatureContext::thdi
int thdi
Definition: signature.h:137
first
trying all byte sequences megabyte in length and selecting the best looking sequence will yield cases to try But first
Definition: rate_distortion.txt:12
evaluate_parameters
static MatchingInfo evaluate_parameters(AVFilterContext *ctx, SignatureContext *sc, MatchingInfo *infos, MatchingInfo bestmatch, int mode)
Definition: signature_lookup.c:418
STATUS_END_REACHED
#define STATUS_END_REACHED
Definition: signature_lookup.c:37
STATUS_NULL
#define STATUS_NULL
Definition: signature_lookup.c:36
MODE_FAST
@ MODE_FAST
Definition: signature.h:44
CoarseSignature::first
struct FineSignature * first
Definition: signature.h:84
s
#define s(width, name)
Definition: cbs_vp9.c:256
SIGELEM_SIZE
#define SIGELEM_SIZE
Definition: signature.h:37
HOUGH_MAX_OFFSET
#define HOUGH_MAX_OFFSET
Definition: signature_lookup.c:28
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:201
ctx
AVFormatContext * ctx
Definition: movenc.c:48
FFABS
#define FFABS(a)
Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they are not representable ...
Definition: common.h:64
av_log_get_level
int av_log_get_level(void)
Get the current log level.
Definition: log.c:437
NULL
#define NULL
Definition: coverity.c:32
signature.h
DIR_PREV
#define DIR_PREV
Definition: signature_lookup.c:31
get_matching_parameters
static MatchingInfo * get_matching_parameters(AVFilterContext *ctx, SignatureContext *sc, FineSignature *first, FineSignature *second)
compares framesignatures and sorts out signatures with a l1 distance above a given threshold.
Definition: signature_lookup.c:174
double
double
Definition: af_crystalizer.c:132
c
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
MatchingInfo::offset
int offset
Definition: signature.h:94
StreamContext
Definition: transcoding.c:51
f
f
Definition: af_crystalizer.c:122
get_jaccarddist
static int get_jaccarddist(SignatureContext *sc, CoarseSignature *first, CoarseSignature *second)
calculates the jaccard distance and evaluates a pair of coarse signatures as good
Definition: signature_lookup.c:115
iterate_frame
static int iterate_frame(double frr, FineSignature **a, FineSignature **b, int fcount, int *bcount, int dir)
Definition: signature_lookup.c:315
size
int size
Definition: twinvq_data.h:10344
union_word
static unsigned int union_word(const uint8_t *first, const uint8_t *second)
Definition: signature_lookup.c:75
DIR_PREV_END
#define DIR_PREV_END
Definition: signature_lookup.c:33
a
The reader does not expect b to be semantically here and if the code is changed by maybe adding a a division or other the signedness will almost certainly be mistaken To avoid this confusion a new type was SUINT is the C unsigned type but it holds a signed int to use the same example SUINT a
Definition: undefined.txt:41
offset
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf offset
Definition: writing_filters.txt:86
DIR_NEXT_END
#define DIR_NEXT_END
Definition: signature_lookup.c:34
SignatureContext::thcomposdist
int thcomposdist
Definition: signature.h:135
get_l1dist
static unsigned int get_l1dist(AVFilterContext *ctx, SignatureContext *sc, const uint8_t *first, const uint8_t *second)
Definition: signature_lookup.c:90
FineSignature
Definition: signature.h:72
SignatureContext
Definition: signature.h:127
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:269
DIR_NEXT
#define DIR_NEXT
Definition: signature_lookup.c:32
av_malloc_array
#define av_malloc_array(a, b)
Definition: tableprint_vlc.h:31
AV_LOG_FATAL
#define AV_LOG_FATAL
Something went wrong and recovery is not possible.
Definition: log.h:174
SignatureContext::thl1
int thl1
Definition: signature.h:136
find_next_coarsecandidate
static int find_next_coarsecandidate(SignatureContext *sc, CoarseSignature *secondstart, CoarseSignature **first, CoarseSignature **second, int start)
step through the coarsesignatures as long as a good candidate is found
Definition: signature_lookup.c:140
CoarseSignature::data
uint8_t data[5][31]
Definition: signature.h:83
CoarseSignature::next
struct CoarseSignature * next
Definition: signature.h:86
mode
mode
Definition: ebur128.h:83
SignatureContext::thworddist
int thworddist
Definition: signature.h:134
MatchingInfo::second
struct FineSignature * second
Definition: signature.h:98
AVFilterContext
An instance of a filter.
Definition: avfilter.h:408
MatchingInfo::next
struct MatchingInfo * next
Definition: signature.h:99
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
MatchingInfo::first
struct FineSignature * first
Definition: signature.h:97
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
intersection_word
static unsigned int intersection_word(const uint8_t *first, const uint8_t *second)
Definition: signature_lookup.c:60
STATUS_BEGIN_REACHED
#define STATUS_BEGIN_REACHED
Definition: signature_lookup.c:38
int
int
Definition: ffmpeg_filter.c:153
sll_free
static void sll_free(MatchingInfo *sll)
Definition: signature_lookup.c:523
CoarseSignature
Definition: signature.h:82
MatchingInfo::matchframes
int matchframes
Definition: signature.h:95