2 * Copyright (C) 2003 Michael Niedermayer <michaelni@gmx.at>
4 * This file is part of FFmpeg.
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (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 GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27 #undef HAVE_AV_CONFIG_H
28 #include "libavutil/mem.h"
29 #include "libavutil/avutil.h"
30 #include "libavutil/lfg.h"
33 /* HACK Duplicated from swscale_internal.h.
34 * Should be removed when a cleaner pixel format system exists. */
35 const char *sws_format_name(enum PixelFormat format
);
38 || (x)==PIX_FMT_GRAY16BE \
39 || (x)==PIX_FMT_GRAY16LE \
41 #define hasChroma(x) (!( \
43 || (x)==PIX_FMT_MONOBLACK \
44 || (x)==PIX_FMT_MONOWHITE \
46 #define isALPHA(x) ( \
48 || (x)==PIX_FMT_BGR32_1 \
49 || (x)==PIX_FMT_RGB32 \
50 || (x)==PIX_FMT_RGB32_1 \
51 || (x)==PIX_FMT_YUVA420P \
54 static uint64_t getSSD(uint8_t *src1
, uint8_t *src2
, int stride1
, int stride2
, int w
, int h
)
59 //printf("%d %d\n", w, h);
63 int d
= src1
[x
+ y
*stride1
] - src2
[x
+ y
*stride2
];
65 //printf("%d", abs(src1[x + y*stride1] - src2[x + y*stride2])/26 );
72 // test by ref -> src -> dst -> out & compare out against ref
74 static int doTest(uint8_t *ref
[4], int refStride
[4], int w
, int h
,
75 enum PixelFormat srcFormat
, enum PixelFormat dstFormat
,
76 int srcW
, int srcH
, int dstW
, int dstH
, int flags
)
78 uint8_t *src
[4] = {0};
79 uint8_t *dst
[4] = {0};
80 uint8_t *out
[4] = {0};
81 int srcStride
[4], dstStride
[4];
83 uint64_t ssdY
, ssdU
=0, ssdV
=0, ssdA
=0;
84 struct SwsContext
*srcContext
= NULL
, *dstContext
= NULL
,
90 // avoid stride % bpp != 0
91 if (srcFormat
==PIX_FMT_RGB24
|| srcFormat
==PIX_FMT_BGR24
)
93 else if (srcFormat
==PIX_FMT_RGB48BE
|| srcFormat
==PIX_FMT_RGB48LE
)
98 if (dstFormat
==PIX_FMT_RGB24
|| dstFormat
==PIX_FMT_BGR24
)
100 else if (dstFormat
==PIX_FMT_RGB48BE
|| dstFormat
==PIX_FMT_RGB48LE
)
101 dstStride
[i
]= dstW
*6;
103 dstStride
[i
]= dstW
*4;
105 /* Image buffers passed into libswscale can be allocated any way you
106 * prefer, as long as they're aligned enough for the architecture, and
107 * they're freed appropriately (such as using av_free for buffers
108 * allocated with av_malloc). */
109 src
[i
]= av_mallocz(srcStride
[i
]*srcH
);
110 dst
[i
]= av_mallocz(dstStride
[i
]*dstH
);
111 out
[i
]= av_mallocz(refStride
[i
]*h
);
112 if (!src
[i
] || !dst
[i
] || !out
[i
]) {
120 srcContext
= sws_getContext(w
, h
, PIX_FMT_YUVA420P
, srcW
, srcH
, srcFormat
, flags
, NULL
, NULL
, NULL
);
122 fprintf(stderr
, "Failed to get %s ---> %s\n",
123 sws_format_name(PIX_FMT_YUVA420P
),
124 sws_format_name(srcFormat
));
129 dstContext
= sws_getContext(srcW
, srcH
, srcFormat
, dstW
, dstH
, dstFormat
, flags
, NULL
, NULL
, NULL
);
131 fprintf(stderr
, "Failed to get %s ---> %s\n",
132 sws_format_name(srcFormat
),
133 sws_format_name(dstFormat
));
138 outContext
= sws_getContext(dstW
, dstH
, dstFormat
, w
, h
, PIX_FMT_YUVA420P
, flags
, NULL
, NULL
, NULL
);
140 fprintf(stderr
, "Failed to get %s ---> %s\n",
141 sws_format_name(dstFormat
),
142 sws_format_name(PIX_FMT_YUVA420P
));
147 // printf("test %X %X %X -> %X %X %X\n", (int)ref[0], (int)ref[1], (int)ref[2],
148 // (int)src[0], (int)src[1], (int)src[2]);
150 sws_scale(srcContext
, ref
, refStride
, 0, h
, src
, srcStride
);
151 sws_scale(dstContext
, src
, srcStride
, 0, srcH
, dst
, dstStride
);
152 sws_scale(outContext
, dst
, dstStride
, 0, dstH
, out
, refStride
);
154 ssdY
= getSSD(ref
[0], out
[0], refStride
[0], refStride
[0], w
, h
);
155 if (hasChroma(srcFormat
) && hasChroma(dstFormat
)) {
156 //FIXME check that output is really gray
157 ssdU
= getSSD(ref
[1], out
[1], refStride
[1], refStride
[1], (w
+1)>>1, (h
+1)>>1);
158 ssdV
= getSSD(ref
[2], out
[2], refStride
[2], refStride
[2], (w
+1)>>1, (h
+1)>>1);
160 if (isALPHA(srcFormat
) && isALPHA(dstFormat
))
161 ssdA
= getSSD(ref
[3], out
[3], refStride
[3], refStride
[3], w
, h
);
168 printf(" %s %dx%d -> %s %4dx%4d flags=%2d SSD=%5"PRId64
",%5"PRId64
",%5"PRId64
",%5"PRId64
"\n",
169 sws_format_name(srcFormat
), srcW
, srcH
,
170 sws_format_name(dstFormat
), dstW
, dstH
,
171 flags
, ssdY
, ssdU
, ssdV
, ssdA
);
176 sws_freeContext(srcContext
);
177 sws_freeContext(dstContext
);
178 sws_freeContext(outContext
);
180 for (i
=0; i
<4; i
++) {
189 static void selfTest(uint8_t *ref
[4], int refStride
[4], int w
, int h
)
191 const int flags
[] = { SWS_FAST_BILINEAR
,
192 SWS_BILINEAR
, SWS_BICUBIC
,
193 SWS_X
, SWS_POINT
, SWS_AREA
, 0 };
196 const int dstW
[] = { srcW
- srcW
/3, srcW
, srcW
+ srcW
/3, 0 };
197 const int dstH
[] = { srcH
- srcH
/3, srcH
, srcH
+ srcH
/3, 0 };
198 enum PixelFormat srcFormat
, dstFormat
;
200 for (srcFormat
= 0; srcFormat
< PIX_FMT_NB
; srcFormat
++) {
201 if (!sws_isSupportedInput(srcFormat
) || !sws_isSupportedOutput(srcFormat
))
204 for (dstFormat
= 0; dstFormat
< PIX_FMT_NB
; dstFormat
++) {
208 if (!sws_isSupportedInput(dstFormat
) || !sws_isSupportedOutput(dstFormat
))
212 sws_format_name(srcFormat
),
213 sws_format_name(dstFormat
));
216 for (i
= 0; dstW
[i
] && !res
; i
++)
217 for (j
= 0; dstH
[j
] && !res
; j
++)
218 for (k
= 0; flags
[k
] && !res
; k
++)
219 res
= doTest(ref
, refStride
, w
, h
, srcFormat
, dstFormat
,
220 srcW
, srcH
, dstW
[i
], dstH
[j
], flags
[k
]);
228 int main(int argc
, char **argv
)
230 uint8_t *rgb_data
= av_malloc (W
*H
*4);
231 uint8_t *rgb_src
[3]= {rgb_data
, NULL
, NULL
};
232 int rgb_stride
[3]={4*W
, 0, 0};
233 uint8_t *data
= av_malloc (4*W
*H
);
234 uint8_t *src
[4]= {data
, data
+W
*H
, data
+W
*H
*2, data
+W
*H
*3};
235 int stride
[4]={W
, W
, W
, W
};
237 struct SwsContext
*sws
;
240 if (!rgb_data
|| !data
)
243 sws
= sws_getContext(W
/12, H
/12, PIX_FMT_RGB32
, W
, H
, PIX_FMT_YUVA420P
, SWS_BILINEAR
, NULL
, NULL
, NULL
);
245 av_lfg_init(&rand
, 1);
247 for (y
=0; y
<H
; y
++) {
248 for (x
=0; x
<W
*4; x
++) {
249 rgb_data
[ x
+ y
*4*W
]= av_lfg_get(&rand
);
252 sws_scale(sws
, rgb_src
, rgb_stride
, 0, H
, src
, stride
);
253 sws_freeContext(sws
);
256 selfTest(src
, stride
, W
, H
);