| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* | ||
| 2 | * Delay Locked Loop based time filter | ||
| 3 | * Copyright (c) 2009 Samalyse | ||
| 4 | * Copyright (c) 2009 Michael Niedermayer | ||
| 5 | * Author: Olivier Guilyardi <olivier samalyse com> | ||
| 6 | * Michael Niedermayer <michaelni gmx at> | ||
| 7 | * | ||
| 8 | * This file is part of FFmpeg. | ||
| 9 | * | ||
| 10 | * FFmpeg is free software; you can redistribute it and/or | ||
| 11 | * modify it under the terms of the GNU Lesser General Public | ||
| 12 | * License as published by the Free Software Foundation; either | ||
| 13 | * version 2.1 of the License, or (at your option) any later version. | ||
| 14 | * | ||
| 15 | * FFmpeg is distributed in the hope that it will be useful, | ||
| 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 18 | * Lesser General Public License for more details. | ||
| 19 | * | ||
| 20 | * You should have received a copy of the GNU Lesser General Public | ||
| 21 | * License along with FFmpeg; if not, write to the Free Software | ||
| 22 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 23 | */ | ||
| 24 | |||
| 25 | #include <math.h> | ||
| 26 | #include <stddef.h> | ||
| 27 | |||
| 28 | #include "libavutil/macros.h" | ||
| 29 | #include "libavutil/mathematics.h" | ||
| 30 | #include "libavutil/mem.h" | ||
| 31 | |||
| 32 | #include "timefilter.h" | ||
| 33 | |||
| 34 | struct TimeFilter { | ||
| 35 | // Delay Locked Loop data. These variables refer to mathematical | ||
| 36 | // concepts described in: http://www.kokkinizita.net/papers/usingdll.pdf | ||
| 37 | double cycle_time; | ||
| 38 | double feedback2_factor; | ||
| 39 | double feedback3_factor; | ||
| 40 | double clock_period; | ||
| 41 | int count; | ||
| 42 | }; | ||
| 43 | |||
| 44 | /* 1 - exp(-x) using a 3-order power series */ | ||
| 45 | ✗ | static double qexpneg(double x) | |
| 46 | { | ||
| 47 | ✗ | return 1 - 1 / (1 + x * (1 + x / 2 * (1 + x / 3))); | |
| 48 | } | ||
| 49 | |||
| 50 | ✗ | TimeFilter *ff_timefilter_new(double time_base, | |
| 51 | double period, | ||
| 52 | double bandwidth) | ||
| 53 | { | ||
| 54 | ✗ | TimeFilter *self = av_mallocz(sizeof(TimeFilter)); | |
| 55 | ✗ | double o = 2 * M_PI * bandwidth * period * time_base; | |
| 56 | |||
| 57 | ✗ | if (!self) | |
| 58 | ✗ | return NULL; | |
| 59 | |||
| 60 | ✗ | self->clock_period = time_base; | |
| 61 | ✗ | self->feedback2_factor = qexpneg(M_SQRT2 * o); | |
| 62 | ✗ | self->feedback3_factor = qexpneg(o * o) / period; | |
| 63 | ✗ | return self; | |
| 64 | } | ||
| 65 | |||
| 66 | ✗ | void ff_timefilter_destroy(TimeFilter *self) | |
| 67 | { | ||
| 68 | ✗ | av_freep(&self); | |
| 69 | ✗ | } | |
| 70 | |||
| 71 | ✗ | void ff_timefilter_reset(TimeFilter *self) | |
| 72 | { | ||
| 73 | ✗ | self->count = 0; | |
| 74 | ✗ | } | |
| 75 | |||
| 76 | ✗ | double ff_timefilter_update(TimeFilter *self, double system_time, double period) | |
| 77 | { | ||
| 78 | ✗ | self->count++; | |
| 79 | ✗ | if (self->count == 1) { | |
| 80 | ✗ | self->cycle_time = system_time; | |
| 81 | } else { | ||
| 82 | double loop_error; | ||
| 83 | ✗ | self->cycle_time += self->clock_period * period; | |
| 84 | ✗ | loop_error = system_time - self->cycle_time; | |
| 85 | |||
| 86 | ✗ | self->cycle_time += FFMAX(self->feedback2_factor, 1.0 / self->count) * loop_error; | |
| 87 | ✗ | self->clock_period += self->feedback3_factor * loop_error; | |
| 88 | } | ||
| 89 | ✗ | return self->cycle_time; | |
| 90 | } | ||
| 91 | |||
| 92 | ✗ | double ff_timefilter_eval(TimeFilter *self, double delta) | |
| 93 | { | ||
| 94 | ✗ | return self->cycle_time + self->clock_period * delta; | |
| 95 | } | ||
| 96 |