2 * VP9 compatible video decoder
4 * Copyright (C) 2013 Ronald S. Bultje <rsbultje gmail com>
5 * Copyright (C) 2013 Clément Bœsch <u pkh me>
7 * This file is part of FFmpeg.
9 * FFmpeg is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * FFmpeg is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with FFmpeg; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26 static av_always_inline
void filter_plane_cols(VP9Context
*s
, int col
, int ss_h
, int ss_v
,
27 uint8_t *lvl
, uint8_t (*mask
)[4],
28 uint8_t *dst
, ptrdiff_t ls
)
30 int y
, x
, bytesperpixel
= s
->bytesperpixel
;
32 // filter edges between columns (e.g. block1 | block2)
33 for (y
= 0; y
< 8; y
+= 2 << ss_v
, dst
+= 16 * ls
, lvl
+= 16 << ss_v
) {
34 uint8_t *ptr
= dst
, *l
= lvl
, *hmask1
= mask
[y
], *hmask2
= mask
[y
+ 1 + ss_v
];
35 unsigned hm1
= hmask1
[0] | hmask1
[1] | hmask1
[2], hm13
= hmask1
[3];
36 unsigned hm2
= hmask2
[1] | hmask2
[2], hm23
= hmask2
[3];
37 unsigned hm
= hm1
| hm2
| hm13
| hm23
;
39 for (x
= 1; hm
& ~(x
- 1); x
<<= 1, ptr
+= 8 * bytesperpixel
>> ss_h
) {
42 int L
= *l
, H
= L
>> 4;
43 int E
= s
->filter_lut
.mblim_lut
[L
], I
= s
->filter_lut
.lim_lut
[L
];
47 av_assert2(l
[8 << ss_v
] == L
);
48 s
->dsp
.loop_filter_16
[0](ptr
, ls
, E
, I
, H
);
50 s
->dsp
.loop_filter_8
[2][0](ptr
, ls
, E
, I
, H
);
55 E
|= s
->filter_lut
.mblim_lut
[L
] << 8;
56 I
|= s
->filter_lut
.lim_lut
[L
] << 8;
57 s
->dsp
.loop_filter_mix2
[!!(hmask1
[1] & x
)]
59 [0](ptr
, ls
, E
, I
, H
);
61 s
->dsp
.loop_filter_8
[!!(hmask1
[1] & x
)]
62 [0](ptr
, ls
, E
, I
, H
);
65 int L
= l
[8 << ss_v
], H
= L
>> 4;
66 int E
= s
->filter_lut
.mblim_lut
[L
], I
= s
->filter_lut
.lim_lut
[L
];
68 s
->dsp
.loop_filter_8
[!!(hmask2
[1] & x
)]
69 [0](ptr
+ 8 * ls
, ls
, E
, I
, H
);
77 int L
= *l
, H
= L
>> 4;
78 int E
= s
->filter_lut
.mblim_lut
[L
], I
= s
->filter_lut
.lim_lut
[L
];
83 E
|= s
->filter_lut
.mblim_lut
[L
] << 8;
84 I
|= s
->filter_lut
.lim_lut
[L
] << 8;
85 s
->dsp
.loop_filter_mix2
[0][0][0](ptr
+ 4 * bytesperpixel
, ls
, E
, I
, H
);
87 s
->dsp
.loop_filter_8
[0][0](ptr
+ 4 * bytesperpixel
, ls
, E
, I
, H
);
89 } else if (hm23
& x
) {
90 int L
= l
[8 << ss_v
], H
= L
>> 4;
91 int E
= s
->filter_lut
.mblim_lut
[L
], I
= s
->filter_lut
.lim_lut
[L
];
93 s
->dsp
.loop_filter_8
[0][0](ptr
+ 8 * ls
+ 4 * bytesperpixel
, ls
, E
, I
, H
);
101 static av_always_inline
void filter_plane_rows(VP9Context
*s
, int row
, int ss_h
, int ss_v
,
102 uint8_t *lvl
, uint8_t (*mask
)[4],
103 uint8_t *dst
, ptrdiff_t ls
)
105 int y
, x
, bytesperpixel
= s
->bytesperpixel
;
108 // filter edges between rows (e.g. ------)
110 for (y
= 0; y
< 8; y
++, dst
+= 8 * ls
>> ss_v
) {
111 uint8_t *ptr
= dst
, *l
= lvl
, *vmask
= mask
[y
];
112 unsigned vm
= vmask
[0] | vmask
[1] | vmask
[2], vm3
= vmask
[3];
114 for (x
= 1; vm
& ~(x
- 1); x
<<= (2 << ss_h
), ptr
+= 16 * bytesperpixel
, l
+= 2 << ss_h
) {
117 int L
= *l
, H
= L
>> 4;
118 int E
= s
->filter_lut
.mblim_lut
[L
], I
= s
->filter_lut
.lim_lut
[L
];
121 if (vmask
[0] & (x
<< (1 + ss_h
))) {
122 av_assert2(l
[1 + ss_h
] == L
);
123 s
->dsp
.loop_filter_16
[1](ptr
, ls
, E
, I
, H
);
125 s
->dsp
.loop_filter_8
[2][1](ptr
, ls
, E
, I
, H
);
127 } else if (vm
& (x
<< (1 + ss_h
))) {
130 E
|= s
->filter_lut
.mblim_lut
[L
] << 8;
131 I
|= s
->filter_lut
.lim_lut
[L
] << 8;
132 s
->dsp
.loop_filter_mix2
[!!(vmask
[1] & x
)]
133 [!!(vmask
[1] & (x
<< (1 + ss_h
)))]
134 [1](ptr
, ls
, E
, I
, H
);
136 s
->dsp
.loop_filter_8
[!!(vmask
[1] & x
)]
137 [1](ptr
, ls
, E
, I
, H
);
139 } else if (vm
& (x
<< (1 + ss_h
))) {
140 int L
= l
[1 + ss_h
], H
= L
>> 4;
141 int E
= s
->filter_lut
.mblim_lut
[L
], I
= s
->filter_lut
.lim_lut
[L
];
143 s
->dsp
.loop_filter_8
[!!(vmask
[1] & (x
<< (1 + ss_h
)))]
144 [1](ptr
+ 8 * bytesperpixel
, ls
, E
, I
, H
);
149 int L
= *l
, H
= L
>> 4;
150 int E
= s
->filter_lut
.mblim_lut
[L
], I
= s
->filter_lut
.lim_lut
[L
];
152 if (vm3
& (x
<< (1 + ss_h
))) {
155 E
|= s
->filter_lut
.mblim_lut
[L
] << 8;
156 I
|= s
->filter_lut
.lim_lut
[L
] << 8;
157 s
->dsp
.loop_filter_mix2
[0][0][1](ptr
+ ls
* 4, ls
, E
, I
, H
);
159 s
->dsp
.loop_filter_8
[0][1](ptr
+ ls
* 4, ls
, E
, I
, H
);
161 } else if (vm3
& (x
<< (1 + ss_h
))) {
162 int L
= l
[1 + ss_h
], H
= L
>> 4;
163 int E
= s
->filter_lut
.mblim_lut
[L
], I
= s
->filter_lut
.lim_lut
[L
];
165 s
->dsp
.loop_filter_8
[0][1](ptr
+ ls
* 4 + 8 * bytesperpixel
, ls
, E
, I
, H
);
178 void ff_vp9_loopfilter_sb(AVCodecContext
*avctx
, VP9Filter
*lflvl
,
179 int row
, int col
, ptrdiff_t yoff
, ptrdiff_t uvoff
)
181 VP9Context
*s
= avctx
->priv_data
;
182 AVFrame
*f
= s
->s
.frames
[CUR_FRAME
].tf
.f
;
183 uint8_t *dst
= f
->data
[0] + yoff
;
184 ptrdiff_t ls_y
= f
->linesize
[0], ls_uv
= f
->linesize
[1];
185 uint8_t (*uv_masks
)[8][4] = lflvl
->mask
[s
->ss_h
| s
->ss_v
];
188 /* FIXME: In how far can we interleave the v/h loopfilter calls? E.g.
189 * if you think of them as acting on a 8x8 block max, we can interleave
190 * each v/h within the single x loop, but that only works if we work on
191 * 8 pixel blocks, and we won't always do that (we want at least 16px
192 * to use SSE2 optimizations, perhaps 32 for AVX2) */
194 filter_plane_cols(s
, col
, 0, 0, lflvl
->level
, lflvl
->mask
[0][0], dst
, ls_y
);
195 filter_plane_rows(s
, row
, 0, 0, lflvl
->level
, lflvl
->mask
[0][1], dst
, ls_y
);
197 for (p
= 0; p
< 2; p
++) {
198 dst
= f
->data
[1 + p
] + uvoff
;
199 filter_plane_cols(s
, col
, s
->ss_h
, s
->ss_v
, lflvl
->level
, uv_masks
[0], dst
, ls_uv
);
200 filter_plane_rows(s
, row
, s
->ss_h
, s
->ss_v
, lflvl
->level
, uv_masks
[1], dst
, ls_uv
);