2 * Copyright (c) 2015 Henrik Gramner
4 * This file is part of FFmpeg.
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.
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.
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.
23 #include "libavcodec/codec_id.h"
24 #include "libavcodec/h264pred.h"
25 #include "libavutil/common.h"
26 #include "libavutil/internal.h"
27 #include "libavutil/intreadwrite.h"
28 #include "libavutil/mem_internal.h"
30 static const int codec_ids
[4] = { AV_CODEC_ID_H264
, AV_CODEC_ID_VP8
, AV_CODEC_ID_RV40
, AV_CODEC_ID_SVQ3
};
32 static const char * const pred4x4_modes
[4][15] = {
34 [VERT_PRED
] = "vertical",
35 [HOR_PRED
] = "horizontal",
37 [DIAG_DOWN_LEFT_PRED
] = "down_left",
38 [DIAG_DOWN_RIGHT_PRED
] = "down_right",
39 [VERT_RIGHT_PRED
] = "vertical_right",
40 [HOR_DOWN_PRED
] = "horizontal_right",
41 [VERT_LEFT_PRED
] = "vertical_left",
42 [HOR_UP_PRED
] = "horizontal_up",
43 [LEFT_DC_PRED
] = "left_dc",
44 [TOP_DC_PRED
] = "top_dc",
45 [DC_128_PRED
] = "dc_128",
48 [VERT_PRED
] = "vertical_vp8",
49 [HOR_PRED
] = "horizontal_vp8",
50 [VERT_LEFT_PRED
] = "vertical_left_vp8",
51 [TM_VP8_PRED
] = "tm_vp8",
52 [DC_127_PRED
] = "dc_127_vp8",
53 [DC_129_PRED
] = "dc_129_vp8",
56 [DIAG_DOWN_LEFT_PRED
] = "down_left_rv40",
57 [VERT_LEFT_PRED
] = "vertical_left_rv40",
58 [HOR_UP_PRED
] = "horizontal_up_rv40",
59 [DIAG_DOWN_LEFT_PRED_RV40_NODOWN
] = "down_left_nodown_rv40",
60 [HOR_UP_PRED_RV40_NODOWN
] = "horizontal_up_nodown_rv40",
61 [VERT_LEFT_PRED_RV40_NODOWN
] = "vertical_left_nodown_rv40",
64 [DIAG_DOWN_LEFT_PRED
] = "down_left_svq3",
68 static const char * const pred8x8_modes
[4][11] = {
71 [HOR_PRED8x8
] = "horizontal",
72 [VERT_PRED8x8
] = "vertical",
73 [PLANE_PRED8x8
] = "plane",
74 [LEFT_DC_PRED8x8
] = "left_dc",
75 [TOP_DC_PRED8x8
] = "top_dc",
76 [DC_128_PRED8x8
] = "dc_128",
77 [ALZHEIMER_DC_L0T_PRED8x8
] = "mad_cow_dc_l0t",
78 [ALZHEIMER_DC_0LT_PRED8x8
] = "mad_cow_dc_0lt",
79 [ALZHEIMER_DC_L00_PRED8x8
] = "mad_cow_dc_l00",
80 [ALZHEIMER_DC_0L0_PRED8x8
] = "mad_cow_dc_0l0",
83 [PLANE_PRED8x8
] = "tm_vp8",
84 [DC_127_PRED8x8
] = "dc_127_vp8",
85 [DC_129_PRED8x8
] = "dc_129_vp8",
88 [DC_PRED8x8
] = "dc_rv40",
89 [LEFT_DC_PRED8x8
] = "left_dc_rv40",
90 [TOP_DC_PRED8x8
] = "top_dc_rv40",
92 /* nothing for SVQ3 */
95 static const char * const pred16x16_modes
[4][9] = {
98 [HOR_PRED8x8
] = "horizontal",
99 [VERT_PRED8x8
] = "vertical",
100 [PLANE_PRED8x8
] = "plane",
101 [LEFT_DC_PRED8x8
] = "left_dc",
102 [TOP_DC_PRED8x8
] = "top_dc",
103 [DC_128_PRED8x8
] = "dc_128",
106 [PLANE_PRED8x8
] = "tm_vp8",
107 [DC_127_PRED8x8
] = "dc_127_vp8",
108 [DC_129_PRED8x8
] = "dc_129_vp8",
111 [PLANE_PRED8x8
] = "plane_rv40",
114 [PLANE_PRED8x8
] = "plane_svq3",
118 static const uint32_t pixel_mask
[3] = { 0xffffffff, 0x01ff01ff, 0x03ff03ff };
120 #define SIZEOF_PIXEL ((bit_depth + 7) / 8)
121 #define BUF_SIZE (3 * 16 * 17)
123 #define check_pred_func(func, name, mode_name) \
124 (mode_name && ((codec_ids[codec] == AV_CODEC_ID_H264) ? \
125 check_func(func, "pred%s_%s_%d", name, mode_name, bit_depth) : \
126 check_func(func, "pred%s_%s", name, mode_name)))
128 #define randomize_buffers() \
130 uint32_t mask = pixel_mask[bit_depth - 8]; \
132 for (i = 0; i < BUF_SIZE; i += 4) { \
133 uint32_t r = rnd() & mask; \
134 AV_WN32A(buf0 + i, r); \
135 AV_WN32A(buf1 + i, r); \
139 #define src0 (buf0 + 4 * 16) /* Offset to allow room for top and left */
140 #define src1 (buf1 + 4 * 16)
142 static void check_pred4x4(H264PredContext
*h
, uint8_t *buf0
, uint8_t *buf1
,
143 int codec
, int chroma_format
, int bit_depth
)
145 if (chroma_format
== 1) {
146 uint8_t *topright
= buf0
+ 2*16;
148 declare_func_emms(AV_CPU_FLAG_MMX
| AV_CPU_FLAG_MMXEXT
, void, uint8_t *src
, const uint8_t *topright
, ptrdiff_t stride
);
150 for (pred_mode
= 0; pred_mode
< 15; pred_mode
++) {
151 if (check_pred_func(h
->pred4x4
[pred_mode
], "4x4", pred4x4_modes
[codec
][pred_mode
])) {
153 call_ref(src0
, topright
, 12*SIZEOF_PIXEL
);
154 call_new(src1
, topright
, 12*SIZEOF_PIXEL
);
155 if (memcmp(buf0
, buf1
, BUF_SIZE
))
157 bench_new(src1
, topright
, 12*SIZEOF_PIXEL
);
163 static void check_pred8x8(H264PredContext
*h
, uint8_t *buf0
, uint8_t *buf1
,
164 int codec
, int chroma_format
, int bit_depth
)
167 declare_func_emms(AV_CPU_FLAG_MMX
| AV_CPU_FLAG_MMXEXT
, void, uint8_t *src
, ptrdiff_t stride
);
169 for (pred_mode
= 0; pred_mode
< 11; pred_mode
++) {
170 if (check_pred_func(h
->pred8x8
[pred_mode
], (chroma_format
== 2) ? "8x16" : "8x8",
171 pred8x8_modes
[codec
][pred_mode
])) {
173 call_ref(src0
, 24*SIZEOF_PIXEL
);
174 call_new(src1
, 24*SIZEOF_PIXEL
);
175 if (memcmp(buf0
, buf1
, BUF_SIZE
))
177 bench_new(src1
, 24*SIZEOF_PIXEL
);
182 static void check_pred16x16(H264PredContext
*h
, uint8_t *buf0
, uint8_t *buf1
,
183 int codec
, int chroma_format
, int bit_depth
)
185 if (chroma_format
== 1) {
187 declare_func_emms(AV_CPU_FLAG_MMX
| AV_CPU_FLAG_MMXEXT
, void, uint8_t *src
, ptrdiff_t stride
);
189 for (pred_mode
= 0; pred_mode
< 9; pred_mode
++) {
190 if (check_pred_func(h
->pred16x16
[pred_mode
], "16x16", pred16x16_modes
[codec
][pred_mode
])) {
194 if (memcmp(buf0
, buf1
, BUF_SIZE
))
202 static void check_pred8x8l(H264PredContext
*h
, uint8_t *buf0
, uint8_t *buf1
,
203 int codec
, int chroma_format
, int bit_depth
)
205 if (chroma_format
== 1 && codec_ids
[codec
] == AV_CODEC_ID_H264
) {
207 declare_func_emms(AV_CPU_FLAG_MMXEXT
, void, uint8_t *src
, int topleft
, int topright
, ptrdiff_t stride
);
209 for (pred_mode
= 0; pred_mode
< 12; pred_mode
++) {
210 if (check_pred_func(h
->pred8x8l
[pred_mode
], "8x8l", pred4x4_modes
[codec
][pred_mode
])) {
212 for (neighbors
= 0; neighbors
<= 0xc000; neighbors
+= 0x4000) {
213 int has_topleft
= neighbors
& 0x8000;
214 int has_topright
= neighbors
& 0x4000;
216 if ((pred_mode
== DIAG_DOWN_RIGHT_PRED
|| pred_mode
== VERT_RIGHT_PRED
) && !has_topleft
)
217 continue; /* Those aren't allowed according to the spec */
220 call_ref(src0
, has_topleft
, has_topright
, 24*SIZEOF_PIXEL
);
221 call_new(src1
, has_topleft
, has_topright
, 24*SIZEOF_PIXEL
);
222 if (memcmp(buf0
, buf1
, BUF_SIZE
))
224 bench_new(src1
, has_topleft
, has_topright
, 24*SIZEOF_PIXEL
);
231 /* TODO: Add tests for H.264 lossless H/V prediction */
233 void checkasm_check_h264pred(void)
235 static const struct {
236 void (*func
)(H264PredContext
*, uint8_t*, uint8_t*, int, int, int);
239 { check_pred4x4
, "pred4x4" },
240 { check_pred8x8
, "pred8x8" },
241 { check_pred16x16
, "pred16x16" },
242 { check_pred8x8l
, "pred8x8l" },
245 LOCAL_ALIGNED_16(uint8_t, buf0
, [BUF_SIZE
]);
246 LOCAL_ALIGNED_16(uint8_t, buf1
, [BUF_SIZE
]);
248 int test
, codec
, chroma_format
, bit_depth
;
250 for (test
= 0; test
< FF_ARRAY_ELEMS(tests
); test
++) {
251 for (codec
= 0; codec
< 4; codec
++) {
252 int codec_id
= codec_ids
[codec
];
253 for (bit_depth
= 8; bit_depth
<= (codec_id
== AV_CODEC_ID_H264
? 10 : 8); bit_depth
++)
254 for (chroma_format
= 1; chroma_format
<= (codec_id
== AV_CODEC_ID_H264
? 2 : 1); chroma_format
++) {
255 ff_h264_pred_init(&h
, codec_id
, bit_depth
, chroma_format
);
256 tests
[test
].func(&h
, buf0
, buf1
, codec
, chroma_format
, bit_depth
);
259 report("%s", tests
[test
].name
);