FFmpeg
Loading...
Searching...
No Matches
h264pred.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2015 Henrik Gramner
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#include <string.h>
22#include "checkasm.h"
23#include "libavcodec/codec_id.h"
24#include "libavcodec/h264pred.h"
25#include "libavutil/common.h"
26#include "libavutil/internal.h"
29
31
32static const char * const pred4x4_modes[4][15] = {
33 { /* H.264 */
34 [VERT_PRED ] = "vertical",
35 [HOR_PRED ] = "horizontal",
36 [DC_PRED ] = "dc",
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_down",
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",
46 },
47 { /* VP8 */
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",
54 },
55 { /* RV40 */
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",
62 },
63 { /* SVQ3 */
64 [DIAG_DOWN_LEFT_PRED] = "down_left_svq3",
65 },
66};
67
68static const char * const pred8x8_modes[4][11] = {
69 { /* H.264 */
70 [DC_PRED8x8 ] = "dc",
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",
81 },
82 { /* VP8 */
83 [DC_PRED8x8 ] = "dc_rv40",
84 [PLANE_PRED8x8 ] = "tm_vp8",
85 [DC_127_PRED8x8] = "dc_127_vp8",
86 [DC_129_PRED8x8] = "dc_129_vp8",
87 },
88 { /* RV40 */
89 [DC_PRED8x8 ] = "dc_rv40",
90 [LEFT_DC_PRED8x8] = "left_dc_rv40",
91 [TOP_DC_PRED8x8 ] = "top_dc_rv40",
92 },
93 /* nothing for SVQ3 */
94};
95
96static const char * const pred16x16_modes[4][9] = {
97 { /* H.264 */
98 [DC_PRED8x8 ] = "dc",
99 [HOR_PRED8x8 ] = "horizontal",
100 [VERT_PRED8x8 ] = "vertical",
101 [PLANE_PRED8x8 ] = "plane",
102 [LEFT_DC_PRED8x8] = "left_dc",
103 [TOP_DC_PRED8x8 ] = "top_dc",
104 [DC_128_PRED8x8 ] = "dc_128",
105 },
106 { /* VP8 */
107 [PLANE_PRED8x8 ] = "tm_vp8",
108 [DC_127_PRED8x8] = "dc_127_vp8",
109 [DC_129_PRED8x8] = "dc_129_vp8",
110 },
111 { /* RV40 */
112 [PLANE_PRED8x8] = "plane_rv40",
113 },
114 { /* SVQ3 */
115 [PLANE_PRED8x8] = "plane_svq3",
116 },
117};
118
119static const uint32_t pixel_mask[3] = { 0xffffffff, 0x01ff01ff, 0x03ff03ff };
120
121#define SIZEOF_PIXEL ((bit_depth + 7) / 8)
122#define BUF_SIZE (3 * 16 * 17)
123
124#define check_pred_func(func, name, mode_name) \
125 (mode_name && ((codec_ids[codec] == AV_CODEC_ID_H264) ? \
126 check_func(func, "pred%s_%s_%d", name, mode_name, bit_depth) : \
127 check_func(func, "pred%s_%s", name, mode_name)))
128
129#define randomize_buffers() \
130 do { \
131 uint32_t mask = pixel_mask[bit_depth - 8]; \
132 int i; \
133 for (i = 0; i < BUF_SIZE; i += 4) { \
134 uint32_t r = rnd() & mask; \
135 AV_WN32A(buf0 + i, r); \
136 AV_WN32A(buf1 + i, r); \
137 } \
138 } while (0)
139
140#define src0 (buf0 + 4 * 16) /* Offset to allow room for top and left */
141#define src1 (buf1 + 4 * 16)
142
143static void check_pred4x4(H264PredContext *h, uint8_t *buf0, uint8_t *buf1,
144 int codec, int chroma_format, int bit_depth)
145{
146 if (chroma_format == 1) {
147 uint8_t *topright = buf0 + 2*16;
148 int pred_mode;
149 declare_func(void, uint8_t *src, const uint8_t *topright, ptrdiff_t stride);
150
151 for (pred_mode = 0; pred_mode < 15; pred_mode++) {
152 if (check_pred_func(h->pred4x4[pred_mode], "4x4", pred4x4_modes[codec][pred_mode])) {
154 call_ref(src0, topright, 12*SIZEOF_PIXEL);
155 call_new(src1, topright, 12*SIZEOF_PIXEL);
156 if (memcmp(buf0, buf1, BUF_SIZE))
157 fail();
158 bench_new(src1, topright, 12*SIZEOF_PIXEL);
159 }
160 }
161 }
162}
163
164static void check_pred8x8(H264PredContext *h, uint8_t *buf0, uint8_t *buf1,
165 int codec, int chroma_format, int bit_depth)
166{
167 int pred_mode;
168 declare_func(void, uint8_t *src, ptrdiff_t stride);
169
170 for (pred_mode = 0; pred_mode < 11; pred_mode++) {
171 if (check_pred_func(h->pred8x8[pred_mode], (chroma_format == 2) ? "8x16" : "8x8",
172 pred8x8_modes[codec][pred_mode])) {
176 if (memcmp(buf0, buf1, BUF_SIZE))
177 fail();
179 }
180 }
181}
182
183static void check_pred16x16(H264PredContext *h, uint8_t *buf0, uint8_t *buf1,
184 int codec, int chroma_format, int bit_depth)
185{
186 if (chroma_format == 1) {
187 int pred_mode;
188 declare_func(void, uint8_t *src, ptrdiff_t stride);
189
190 for (pred_mode = 0; pred_mode < 9; pred_mode++) {
191 if (check_pred_func(h->pred16x16[pred_mode], "16x16", pred16x16_modes[codec][pred_mode])) {
193 call_ref(src0, 48);
194 call_new(src1, 48);
195 if (memcmp(buf0, buf1, BUF_SIZE))
196 fail();
197 bench_new(src1, 48);
198 }
199 }
200 }
201}
202
203static void check_pred8x8l(H264PredContext *h, uint8_t *buf0, uint8_t *buf1,
204 int codec, int chroma_format, int bit_depth)
205{
206 if (chroma_format == 1 && codec_ids[codec] == AV_CODEC_ID_H264) {
207 int pred_mode;
208 declare_func(void, uint8_t *src, int topleft, int topright, ptrdiff_t stride);
209
210 for (pred_mode = 0; pred_mode < 12; pred_mode++) {
211 if (check_pred_func(h->pred8x8l[pred_mode], "8x8l", pred4x4_modes[codec][pred_mode])) {
212 int neighbors;
213 for (neighbors = 0; neighbors <= 0xc000; neighbors += 0x4000) {
214 int has_topleft = neighbors & 0x8000;
215 int has_topright = neighbors & 0x4000;
216
217 if ((pred_mode == DIAG_DOWN_RIGHT_PRED || pred_mode == VERT_RIGHT_PRED) && !has_topleft)
218 continue; /* Those aren't allowed according to the spec */
219
221 call_ref(src0, has_topleft, has_topright, 24*SIZEOF_PIXEL);
222 call_new(src1, has_topleft, has_topright, 24*SIZEOF_PIXEL);
223 if (memcmp(buf0, buf1, BUF_SIZE))
224 fail();
225 bench_new(src1, has_topleft, has_topright, 24*SIZEOF_PIXEL);
226 }
227 }
228 }
229 }
230}
231
232/* TODO: Add tests for H.264 lossless H/V prediction */
233
235{
236 static const struct {
237 void (*func)(H264PredContext*, uint8_t*, uint8_t*, int, int, int);
238 const char *name;
239 } tests[] = {
240 { check_pred4x4, "pred4x4" },
241 { check_pred8x8, "pred8x8" },
242 { check_pred16x16, "pred16x16" },
243 { check_pred8x8l, "pred8x8l" },
244 };
245
246 LOCAL_ALIGNED_16(uint8_t, buf0, [BUF_SIZE]);
247 LOCAL_ALIGNED_16(uint8_t, buf1, [BUF_SIZE]);
249 int test, codec, chroma_format, bit_depth;
250
251 for (test = 0; test < FF_ARRAY_ELEMS(tests); test++) {
252 for (codec = 0; codec < 4; codec++) {
253 int codec_id = codec_ids[codec];
254 for (bit_depth = 8; bit_depth <= (codec_id == AV_CODEC_ID_H264 ? 10 : 8); bit_depth++)
255 for (chroma_format = 1; chroma_format <= (codec_id == AV_CODEC_ID_H264 ? 2 : 1); chroma_format++) {
256 ff_h264_pred_init(&h, codec_id, bit_depth, chroma_format);
257 tests[test].func(&h, buf0, buf1, codec, chroma_format, bit_depth);
258 }
259 }
260 report("%s", tests[test].name);
261 }
262}
static enum AVCodecID codec_ids[]
static void bit_depth(AudioStatsContext *s, const uint64_t *const mask, uint8_t *depth)
Definition af_astats.c:246
common internal and external API header
const TestCase tests[]
Definition fifo_muxer.c:363
#define declare_func
Definition test.h:489
#define fail
Definition test.h:479
#define bench_new
Definition test.h:487
#define call_new
Definition test.h:486
#define call_ref
Definition test.h:485
#define report
Definition test.h:480
@ AV_CODEC_ID_SVQ3
Definition codec_id.h:73
@ AV_CODEC_ID_H264
Definition codec_id.h:77
@ AV_CODEC_ID_VP8
Definition codec_id.h:190
@ AV_CODEC_ID_RV40
Definition codec_id.h:119
H.264 / AVC / MPEG-4 prediction functions.
#define DIAG_DOWN_LEFT_PRED_RV40_NODOWN
Definition h264pred.h:54
#define TOP_DC_PRED
Definition h264pred.h:50
#define ALZHEIMER_DC_0LT_PRED8x8
Definition h264pred.h:80
#define TOP_DC_PRED8x8
Definition h264pred.h:75
#define DC_129_PRED
Definition h264pred.h:66
#define DC_127_PRED
Definition h264pred.h:65
#define ALZHEIMER_DC_L00_PRED8x8
Definition h264pred.h:81
#define HOR_UP_PRED_RV40_NODOWN
Definition h264pred.h:55
#define ALZHEIMER_DC_L0T_PRED8x8
Definition h264pred.h:79
#define VERT_PRED
Prediction types.
Definition h264pred.h:38
#define HOR_PRED8x8
Definition h264pred.h:69
#define DC_128_PRED
Definition h264pred.h:51
#define DC_127_PRED8x8
Definition h264pred.h:85
#define VERT_LEFT_PRED
Definition h264pred.h:45
#define HOR_DOWN_PRED
Definition h264pred.h:44
#define VERT_PRED8x8
Definition h264pred.h:70
#define DC_129_PRED8x8
Definition h264pred.h:86
#define DIAG_DOWN_LEFT_PRED
Definition h264pred.h:41
#define LEFT_DC_PRED
Definition h264pred.h:49
#define TM_VP8_PRED
"True Motion", used instead of plane
Definition h264pred.h:59
#define DC_PRED8x8
Definition h264pred.h:68
#define HOR_UP_PRED
Definition h264pred.h:46
#define LEFT_DC_PRED8x8
Definition h264pred.h:74
#define ALZHEIMER_DC_0L0_PRED8x8
Definition h264pred.h:82
#define VERT_LEFT_PRED_RV40_NODOWN
Definition h264pred.h:56
#define DIAG_DOWN_RIGHT_PRED
Definition h264pred.h:42
#define HOR_PRED
Definition h264pred.h:39
#define DC_PRED
Definition h264pred.h:40
#define PLANE_PRED8x8
Definition h264pred.h:71
#define DC_128_PRED8x8
Definition h264pred.h:76
#define VERT_RIGHT_PRED
Definition h264pred.h:43
av_cold void ff_h264_pred_init(H264PredContext *h, int codec_id, const int bit_depth, int chroma_format_idc)
Set the intra prediction function pointers.
Definition h264pred.c:437
int(* func)(AVBPrint *dst, const char *in, const char *arg)
Definition jacosubdec.c:66
common internal API header
#define LOCAL_ALIGNED_16(t, v,...)
const char * name
Definition qsvenc.c:142
#define BUF_SIZE
Definition setpts.c:159
#define FF_ARRAY_ELEMS(a)
Context for storing H.264 prediction functions.
Definition h264pred.h:94
Definition idctdsp.c:35
#define stride
#define SIZEOF_PIXEL
Definition h264chroma.c:28
static const uint32_t pixel_mask[5]
Definition h264dsp.c:31
#define randomize_buffers()
Definition h264pred.c:129
static const char *const pred8x8_modes[4][11]
Definition h264pred.c:68
static void check_pred8x8(H264PredContext *h, uint8_t *buf0, uint8_t *buf1, int codec, int chroma_format, int bit_depth)
Definition h264pred.c:164
static void check_pred4x4(H264PredContext *h, uint8_t *buf0, uint8_t *buf1, int codec, int chroma_format, int bit_depth)
Definition h264pred.c:143
static void check_pred16x16(H264PredContext *h, uint8_t *buf0, uint8_t *buf1, int codec, int chroma_format, int bit_depth)
Definition h264pred.c:183
void checkasm_check_h264pred(void)
Definition h264pred.c:234
#define src1
Definition h264pred.c:141
#define check_pred_func(func, name, mode_name)
Definition h264pred.c:124
static const char *const pred4x4_modes[4][15]
Definition h264pred.c:32
static void check_pred8x8l(H264PredContext *h, uint8_t *buf0, uint8_t *buf1, int codec, int chroma_format, int bit_depth)
Definition h264pred.c:203
#define src0
Definition h264pred.c:140
static const char *const pred16x16_modes[4][9]
Definition h264pred.c:96
#define src
Definition vp8dsp.c:248
enum AVCodecID codec_id