| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* | ||
| 2 | * Copyright (C) 2007 Marco Gerards <marco@gnu.org> | ||
| 3 | * Copyright (C) 2016 Open Broadcast Systems Ltd. | ||
| 4 | * Author 2016 Rostislav Pehlivanov <atomnuker@gmail.com> | ||
| 5 | * | ||
| 6 | * This file is part of FFmpeg. | ||
| 7 | * | ||
| 8 | * FFmpeg is free software; you can redistribute it and/or | ||
| 9 | * modify it under the terms of the GNU Lesser General Public | ||
| 10 | * License as published by the Free Software Foundation; either | ||
| 11 | * version 2.1 of the License, or (at your option) any later version. | ||
| 12 | * | ||
| 13 | * FFmpeg is distributed in the hope that it will be useful, | ||
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 16 | * Lesser General Public License for more details. | ||
| 17 | * | ||
| 18 | * You should have received a copy of the GNU Lesser General Public | ||
| 19 | * License along with FFmpeg; if not, write to the Free Software | ||
| 20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 21 | */ | ||
| 22 | |||
| 23 | #include "libavutil/attributes.h" | ||
| 24 | #include "libavutil/mem.h" | ||
| 25 | #include "vc2enc_dwt.h" | ||
| 26 | |||
| 27 | /* Since the transforms spit out interleaved coefficients, this function | ||
| 28 | * rearranges the coefficients into the more traditional subdivision, | ||
| 29 | * making it easier to encode and perform another level. */ | ||
| 30 | 1980 | static av_always_inline void deinterleave(dwtcoef *linell, ptrdiff_t stride, | |
| 31 | int width, int height, dwtcoef *synthl) | ||
| 32 | { | ||
| 33 | int x, y; | ||
| 34 | 1980 | ptrdiff_t synthw = width << 1; | |
| 35 | 1980 | dwtcoef *linehl = linell + width; | |
| 36 | 1980 | dwtcoef *linelh = linell + height*stride; | |
| 37 | 1980 | dwtcoef *linehh = linelh + width; | |
| 38 | |||
| 39 | /* Deinterleave the coefficients. */ | ||
| 40 |
2/2✓ Branch 0 taken 121500 times.
✓ Branch 1 taken 1980 times.
|
123480 | for (y = 0; y < height; y++) { |
| 41 |
2/2✓ Branch 0 taken 11865150 times.
✓ Branch 1 taken 121500 times.
|
11986650 | for (x = 0; x < width; x++) { |
| 42 | 11865150 | linell[x] = synthl[(x << 1)]; | |
| 43 | 11865150 | linehl[x] = synthl[(x << 1) + 1]; | |
| 44 | 11865150 | linelh[x] = synthl[(x << 1) + synthw]; | |
| 45 | 11865150 | linehh[x] = synthl[(x << 1) + synthw + 1]; | |
| 46 | } | ||
| 47 | 121500 | synthl += synthw << 1; | |
| 48 | 121500 | linell += stride; | |
| 49 | 121500 | linelh += stride; | |
| 50 | 121500 | linehl += stride; | |
| 51 | 121500 | linehh += stride; | |
| 52 | } | ||
| 53 | 1980 | } | |
| 54 | |||
| 55 | 1620 | static void vc2_subband_dwt_97(VC2TransformContext *t, dwtcoef *data, | |
| 56 | ptrdiff_t stride, int width, int height) | ||
| 57 | { | ||
| 58 | int x, y; | ||
| 59 | 1620 | dwtcoef *datal = data, *synth = t->buffer, *synthl = synth; | |
| 60 | 1620 | const ptrdiff_t synth_width = width << 1; | |
| 61 | 1620 | const ptrdiff_t synth_height = height << 1; | |
| 62 | |||
| 63 | /* | ||
| 64 | * Shift in one bit that is used for additional precision and copy | ||
| 65 | * the data to the buffer. | ||
| 66 | */ | ||
| 67 |
2/2✓ Branch 0 taken 194400 times.
✓ Branch 1 taken 1620 times.
|
196020 | for (y = 0; y < synth_height; y++) { |
| 68 |
2/2✓ Branch 0 taken 39382200 times.
✓ Branch 1 taken 194400 times.
|
39576600 | for (x = 0; x < synth_width; x++) |
| 69 | 39382200 | synthl[x] = datal[x] * 2; | |
| 70 | 194400 | synthl += synth_width; | |
| 71 | 194400 | datal += stride; | |
| 72 | } | ||
| 73 | |||
| 74 | /* Horizontal synthesis. */ | ||
| 75 | 1620 | synthl = synth; | |
| 76 |
2/2✓ Branch 0 taken 194400 times.
✓ Branch 1 taken 1620 times.
|
196020 | for (y = 0; y < synth_height; y++) { |
| 77 | /* Lifting stage 2. */ | ||
| 78 | 194400 | synthl[1] -= (8*synthl[0] + 9*synthl[2] - synthl[4] + 8) >> 4; | |
| 79 |
2/2✓ Branch 0 taken 19107900 times.
✓ Branch 1 taken 194400 times.
|
19302300 | for (x = 1; x < width - 2; x++) |
| 80 | 19107900 | synthl[2*x + 1] -= (9*synthl[2*x] + 9*synthl[2*x + 2] - synthl[2*x + 4] - | |
| 81 | 19107900 | synthl[2 * x - 2] + 8) >> 4; | |
| 82 | 194400 | synthl[synth_width - 1] -= (17*synthl[synth_width - 2] - | |
| 83 | 194400 | synthl[synth_width - 4] + 8) >> 4; | |
| 84 | 194400 | synthl[synth_width - 3] -= (8*synthl[synth_width - 2] + | |
| 85 | 194400 | 9*synthl[synth_width - 4] - | |
| 86 | 194400 | synthl[synth_width - 6] + 8) >> 4; | |
| 87 | /* Lifting stage 1. */ | ||
| 88 | 194400 | synthl[0] += (synthl[1] + synthl[1] + 2) >> 2; | |
| 89 |
2/2✓ Branch 0 taken 19302300 times.
✓ Branch 1 taken 194400 times.
|
19496700 | for (x = 1; x < width - 1; x++) |
| 90 | 19302300 | synthl[2*x] += (synthl[2*x - 1] + synthl[2*x + 1] + 2) >> 2; | |
| 91 | |||
| 92 | 194400 | synthl[synth_width - 2] += (synthl[synth_width - 3] + | |
| 93 | 194400 | synthl[synth_width - 1] + 2) >> 2; | |
| 94 | 194400 | synthl += synth_width; | |
| 95 | } | ||
| 96 | |||
| 97 | /* Vertical synthesis: Lifting stage 2. */ | ||
| 98 | 1620 | synthl = synth + synth_width; | |
| 99 |
2/2✓ Branch 0 taken 207900 times.
✓ Branch 1 taken 1620 times.
|
209520 | for (x = 0; x < synth_width; x++) |
| 100 | 207900 | synthl[x] -= (8*synthl[x - synth_width] + 9*synthl[x + synth_width] - | |
| 101 | 207900 | synthl[x + 3 * synth_width] + 8) >> 4; | |
| 102 | |||
| 103 | 1620 | synthl = synth + (synth_width << 1); | |
| 104 |
2/2✓ Branch 0 taken 92340 times.
✓ Branch 1 taken 1620 times.
|
93960 | for (y = 1; y < height - 2; y++) { |
| 105 |
2/2✓ Branch 0 taken 19067400 times.
✓ Branch 1 taken 92340 times.
|
19159740 | for (x = 0; x < synth_width; x++) |
| 106 | 19067400 | synthl[x + synth_width] -= (9*synthl[x] + | |
| 107 | 19067400 | 9*synthl[x + 2 * synth_width] - | |
| 108 | 19067400 | synthl[x - 2 * synth_width] - | |
| 109 | 19067400 | synthl[x + 4 * synth_width] + 8) >> 4; | |
| 110 | 92340 | synthl += synth_width << 1; | |
| 111 | } | ||
| 112 | |||
| 113 | 1620 | synthl = synth + (synth_height - 1) * synth_width; | |
| 114 |
2/2✓ Branch 0 taken 207900 times.
✓ Branch 1 taken 1620 times.
|
209520 | for (x = 0; x < synth_width; x++) { |
| 115 | 207900 | synthl[x] -= (17*synthl[x - synth_width] - | |
| 116 | 207900 | synthl[x - 3*synth_width] + 8) >> 4; | |
| 117 | 207900 | synthl[x - 2*synth_width] -= (9*synthl[x - 3*synth_width] + | |
| 118 | 207900 | 8*synthl[x - 1*synth_width] - synthl[x - 5*synth_width] + 8) >> 4; | |
| 119 | } | ||
| 120 | |||
| 121 | /* Vertical synthesis: Lifting stage 1. */ | ||
| 122 | 1620 | synthl = synth; | |
| 123 |
2/2✓ Branch 0 taken 207900 times.
✓ Branch 1 taken 1620 times.
|
209520 | for (x = 0; x < synth_width; x++) |
| 124 | 207900 | synthl[x] += (synthl[x + synth_width] + synthl[x + synth_width] + 2) >> 2; | |
| 125 | |||
| 126 | 1620 | synthl = synth + (synth_width << 1); | |
| 127 |
2/2✓ Branch 0 taken 93960 times.
✓ Branch 1 taken 1620 times.
|
95580 | for (y = 1; y < height - 1; y++) { |
| 128 |
2/2✓ Branch 0 taken 19275300 times.
✓ Branch 1 taken 93960 times.
|
19369260 | for (x = 0; x < synth_width; x++) |
| 129 | 19275300 | synthl[x] += (synthl[x - synth_width] + synthl[x + synth_width] + 2) >> 2; | |
| 130 | 93960 | synthl += synth_width << 1; | |
| 131 | } | ||
| 132 | |||
| 133 | 1620 | synthl = synth + (synth_height - 2) * synth_width; | |
| 134 |
2/2✓ Branch 0 taken 207900 times.
✓ Branch 1 taken 1620 times.
|
209520 | for (x = 0; x < synth_width; x++) |
| 135 | 207900 | synthl[x] += (synthl[x - synth_width] + synthl[x + synth_width] + 2) >> 2; | |
| 136 | |||
| 137 | 1620 | deinterleave(data, stride, width, height, synth); | |
| 138 | 1620 | } | |
| 139 | |||
| 140 | 180 | static void vc2_subband_dwt_53(VC2TransformContext *t, dwtcoef *data, | |
| 141 | ptrdiff_t stride, int width, int height) | ||
| 142 | { | ||
| 143 | int x, y; | ||
| 144 | 180 | dwtcoef *synth = t->buffer, *synthl = synth, *datal = data; | |
| 145 | 180 | const ptrdiff_t synth_width = width << 1; | |
| 146 | 180 | const ptrdiff_t synth_height = height << 1; | |
| 147 | |||
| 148 | /* | ||
| 149 | * Shift in one bit that is used for additional precision and copy | ||
| 150 | * the data to the buffer. | ||
| 151 | */ | ||
| 152 |
2/2✓ Branch 0 taken 24300 times.
✓ Branch 1 taken 180 times.
|
24480 | for (y = 0; y < synth_height; y++) { |
| 153 |
2/2✓ Branch 0 taken 4039200 times.
✓ Branch 1 taken 24300 times.
|
4063500 | for (x = 0; x < synth_width; x++) |
| 154 | 4039200 | synthl[x] = datal[x] * 2; | |
| 155 | 24300 | synthl += synth_width; | |
| 156 | 24300 | datal += stride; | |
| 157 | } | ||
| 158 | |||
| 159 | /* Horizontal synthesis. */ | ||
| 160 | 180 | synthl = synth; | |
| 161 |
2/2✓ Branch 0 taken 24300 times.
✓ Branch 1 taken 180 times.
|
24480 | for (y = 0; y < synth_height; y++) { |
| 162 | /* Lifting stage 2. */ | ||
| 163 |
2/2✓ Branch 0 taken 1995300 times.
✓ Branch 1 taken 24300 times.
|
2019600 | for (x = 0; x < width - 1; x++) |
| 164 | 1995300 | synthl[2 * x + 1] -= (synthl[2 * x] + synthl[2 * x + 2] + 1) >> 1; | |
| 165 | |||
| 166 | 24300 | synthl[synth_width - 1] -= (2*synthl[synth_width - 2] + 1) >> 1; | |
| 167 | |||
| 168 | /* Lifting stage 1. */ | ||
| 169 | 24300 | synthl[0] += (2*synthl[1] + 2) >> 2; | |
| 170 |
2/2✓ Branch 0 taken 1971000 times.
✓ Branch 1 taken 24300 times.
|
1995300 | for (x = 1; x < width - 1; x++) |
| 171 | 1971000 | synthl[2 * x] += (synthl[2 * x - 1] + synthl[2 * x + 1] + 2) >> 2; | |
| 172 | |||
| 173 | 24300 | synthl[synth_width - 2] += (synthl[synth_width - 3] + synthl[synth_width - 1] + 2) >> 2; | |
| 174 | |||
| 175 | 24300 | synthl += synth_width; | |
| 176 | } | ||
| 177 | |||
| 178 | /* Vertical synthesis: Lifting stage 2. */ | ||
| 179 | 180 | synthl = synth + synth_width; | |
| 180 |
2/2✓ Branch 0 taken 19800 times.
✓ Branch 1 taken 180 times.
|
19980 | for (x = 0; x < synth_width; x++) |
| 181 | 19800 | synthl[x] -= (synthl[x - synth_width] + synthl[x + synth_width] + 1) >> 1; | |
| 182 | |||
| 183 | 180 | synthl = synth + (synth_width << 1); | |
| 184 |
2/2✓ Branch 0 taken 11790 times.
✓ Branch 1 taken 180 times.
|
11970 | for (y = 1; y < height - 1; y++) { |
| 185 |
2/2✓ Branch 0 taken 1980000 times.
✓ Branch 1 taken 11790 times.
|
1991790 | for (x = 0; x < synth_width; x++) |
| 186 | 1980000 | synthl[x + synth_width] -= (synthl[x] + synthl[x + synth_width * 2] + 1) >> 1; | |
| 187 | 11790 | synthl += (synth_width << 1); | |
| 188 | } | ||
| 189 | |||
| 190 | 180 | synthl = synth + (synth_height - 1) * synth_width; | |
| 191 |
2/2✓ Branch 0 taken 19800 times.
✓ Branch 1 taken 180 times.
|
19980 | for (x = 0; x < synth_width; x++) |
| 192 | 19800 | synthl[x] -= (2*synthl[x - synth_width] + 1) >> 1; | |
| 193 | |||
| 194 | /* Vertical synthesis: Lifting stage 1. */ | ||
| 195 | 180 | synthl = synth; | |
| 196 |
2/2✓ Branch 0 taken 19800 times.
✓ Branch 1 taken 180 times.
|
19980 | for (x = 0; x < synth_width; x++) |
| 197 | 19800 | synthl[x] += (2*synthl[synth_width + x] + 2) >> 2; | |
| 198 | |||
| 199 | 180 | synthl = synth + (synth_width << 1); | |
| 200 |
2/2✓ Branch 0 taken 11790 times.
✓ Branch 1 taken 180 times.
|
11970 | for (y = 1; y < height - 1; y++) { |
| 201 |
2/2✓ Branch 0 taken 1980000 times.
✓ Branch 1 taken 11790 times.
|
1991790 | for (x = 0; x < synth_width; x++) |
| 202 | 1980000 | synthl[x] += (synthl[x + synth_width] + synthl[x - synth_width] + 2) >> 2; | |
| 203 | 11790 | synthl += (synth_width << 1); | |
| 204 | } | ||
| 205 | |||
| 206 | 180 | synthl = synth + (synth_height - 2)*synth_width; | |
| 207 |
2/2✓ Branch 0 taken 19800 times.
✓ Branch 1 taken 180 times.
|
19980 | for (x = 0; x < synth_width; x++) |
| 208 | 19800 | synthl[x] += (synthl[x - synth_width] + synthl[x + synth_width] + 2) >> 2; | |
| 209 | |||
| 210 | |||
| 211 | 180 | deinterleave(data, stride, width, height, synth); | |
| 212 | 180 | } | |
| 213 | |||
| 214 | 180 | static av_always_inline void dwt_haar(VC2TransformContext *t, dwtcoef *data, | |
| 215 | ptrdiff_t stride, int width, int height, | ||
| 216 | const int s) | ||
| 217 | { | ||
| 218 | int x, y; | ||
| 219 | 180 | dwtcoef *synth = t->buffer, *synthl = synth, *datal = data; | |
| 220 | 180 | const ptrdiff_t synth_width = width << 1; | |
| 221 | 180 | const ptrdiff_t synth_height = height << 1; | |
| 222 | |||
| 223 | /* Horizontal synthesis. */ | ||
| 224 |
2/2✓ Branch 0 taken 24300 times.
✓ Branch 1 taken 180 times.
|
24480 | for (y = 0; y < synth_height; y++) { |
| 225 |
2/2✓ Branch 0 taken 2019600 times.
✓ Branch 1 taken 24300 times.
|
2043900 | for (x = 0; x < synth_width; x += 2) { |
| 226 | 2019600 | synthl[y*synth_width + x + 1] = (datal[y*stride + x + 1] - datal[y*stride + x]) * (1 << s); | |
| 227 | 2019600 | synthl[y*synth_width + x] = datal[y*stride + x + 0] * (1 << s) + | |
| 228 | 2019600 | ((synthl[y*synth_width + x + 1] + 1) >> 1); | |
| 229 | } | ||
| 230 | } | ||
| 231 | |||
| 232 | /* Vertical synthesis. */ | ||
| 233 |
2/2✓ Branch 0 taken 19800 times.
✓ Branch 1 taken 180 times.
|
19980 | for (x = 0; x < synth_width; x++) { |
| 234 |
2/2✓ Branch 0 taken 2019600 times.
✓ Branch 1 taken 19800 times.
|
2039400 | for (y = 0; y < synth_height; y += 2) { |
| 235 | 2019600 | synthl[(y + 1)*synth_width + x] = synthl[(y + 1)*synth_width + x] - | |
| 236 | 2019600 | synthl[y*synth_width + x]; | |
| 237 | 2019600 | synthl[y*synth_width + x] = synthl[y*synth_width + x] + | |
| 238 | 2019600 | ((synthl[(y + 1)*synth_width + x] + 1) >> 1); | |
| 239 | } | ||
| 240 | } | ||
| 241 | |||
| 242 | 180 | deinterleave(data, stride, width, height, synth); | |
| 243 | 180 | } | |
| 244 | |||
| 245 | ✗ | static void vc2_subband_dwt_haar(VC2TransformContext *t, dwtcoef *data, | |
| 246 | ptrdiff_t stride, int width, int height) | ||
| 247 | { | ||
| 248 | ✗ | dwt_haar(t, data, stride, width, height, 0); | |
| 249 | ✗ | } | |
| 250 | |||
| 251 | 180 | static void vc2_subband_dwt_haar_shift(VC2TransformContext *t, dwtcoef *data, | |
| 252 | ptrdiff_t stride, int width, int height) | ||
| 253 | { | ||
| 254 | 180 | dwt_haar(t, data, stride, width, height, 1); | |
| 255 | 180 | } | |
| 256 | |||
| 257 | 99 | av_cold int ff_vc2enc_init_transforms(VC2TransformContext *s, int p_stride, | |
| 258 | int p_height, int slice_w, int slice_h) | ||
| 259 | { | ||
| 260 | 99 | s->vc2_subband_dwt[VC2_TRANSFORM_9_7] = vc2_subband_dwt_97; | |
| 261 | 99 | s->vc2_subband_dwt[VC2_TRANSFORM_5_3] = vc2_subband_dwt_53; | |
| 262 | 99 | s->vc2_subband_dwt[VC2_TRANSFORM_HAAR] = vc2_subband_dwt_haar; | |
| 263 | 99 | s->vc2_subband_dwt[VC2_TRANSFORM_HAAR_S] = vc2_subband_dwt_haar_shift; | |
| 264 | |||
| 265 | /* Pad by the slice size, only matters for non-Haar wavelets */ | ||
| 266 | 99 | s->buffer = av_calloc((p_stride + slice_w)*(p_height + slice_h), sizeof(dwtcoef)); | |
| 267 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 99 times.
|
99 | if (!s->buffer) |
| 268 | ✗ | return 1; | |
| 269 | |||
| 270 | 99 | s->padding = (slice_h >> 1)*p_stride + (slice_w >> 1); | |
| 271 | 99 | s->buffer += s->padding; | |
| 272 | |||
| 273 | 99 | return 0; | |
| 274 | } | ||
| 275 | |||
| 276 | 99 | av_cold void ff_vc2enc_free_transforms(VC2TransformContext *s) | |
| 277 | { | ||
| 278 |
1/2✓ Branch 0 taken 99 times.
✗ Branch 1 not taken.
|
99 | if (s->buffer) { |
| 279 | 99 | av_free(s->buffer - s->padding); | |
| 280 | 99 | s->buffer = NULL; | |
| 281 | } | ||
| 282 | 99 | } | |
| 283 |