FFmpeg
floatimg_cmp.c
Go to the documentation of this file.
1 /*
2  * This file is part of FFmpeg.
3  *
4  * FFmpeg is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * FFmpeg is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with FFmpeg; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <math.h>
23 #include <inttypes.h>
24 #include <float.h>
25 
26 #include "libavutil/avutil.h"
27 #include "libavutil/imgutils.h"
28 #include "libavutil/intfloat.h"
29 #include "libavutil/intreadwrite.h"
30 #include "libavutil/lfg.h"
31 #include "libavutil/mem.h"
32 #include "libavutil/parseutils.h"
33 #include "libavutil/pixdesc.h"
34 
35 #include "libswscale/swscale.h"
36 
37 #define DEFAULT_W 96
38 #define DEFAULT_H 96
39 
40 static const enum AVPixelFormat pix_fmts[] = {
58 };
59 
60 const char *usage = "floatimg_cmp -pixel_format <pix_fmt> -size <image_size> -ref <testfile>\n";
61 
62 int main(int argc, char **argv)
63 {
64  enum AVPixelFormat inFormat = AV_PIX_FMT_NONE;
65  enum AVPixelFormat dstFormat = AV_PIX_FMT_NONE;
66  const AVPixFmtDescriptor *desc;
67  uint8_t *ptr;
68  uint32_t *in, *out;
69 
70  uint8_t *rgbIn[4] = {NULL, NULL, NULL, NULL};
71  uint8_t *rgbOut[4] = {NULL, NULL, NULL, NULL};
72  int rgbStride[4];
73 
74  uint8_t *dst[4] = {NULL, NULL, NULL, NULL};
75  int dstStride[4];
76 
77  int i, x, y, p, size, count;
78  int res = -1;
79  int w = -1;
80  int h = -1;
81  union av_intfloat32 v0, v1;
82 
83  double sum;
84  float minimum, maximum, diff;
85 
86  struct SwsContext *sws = NULL;
87  AVLFG rand;
88  FILE *fp = NULL;
89 
90  for (i = 1; i < argc; i += 2) {
91  if (argv[i][0] != '-' || i + 1 == argc)
92  goto bad_option;
93  if (!strcmp(argv[i], "-ref")) {
94  fp = fopen(argv[i + 1], "rb");
95  if (!fp) {
96  fprintf(stderr, "could not open '%s'\n", argv[i + 1]);
97  goto end;
98  }
99  } else if (!strcmp(argv[i], "-size")) {
100  res = av_parse_video_size(&w, &h, argv[i + 1]);
101  if (res < 0) {
102  fprintf(stderr, "invalid video size %s\n", argv[i + 1]);
103  goto end;
104  }
105  } else if (!strcmp(argv[i], "-pixel_format")) {
106  inFormat = av_get_pix_fmt(argv[i + 1]);
107  if (inFormat == AV_PIX_FMT_NONE) {
108  fprintf(stderr, "invalid pixel format %s\n", argv[i + 1]);
109  goto end;
110  }
111  } else {
112 bad_option:
113  fprintf(stderr, "%s", usage);
114  fprintf(stderr, "bad option or argument missing (%s)\n", argv[i]);
115  goto end;
116  };
117  }
118 
119  if (!fp) {
120  inFormat = AV_PIX_FMT_GBRPF32LE;
121  w = DEFAULT_W;
122  h = DEFAULT_H;
123  }
124 
125  if (w <= 0 || h <= 0) {
126  fprintf(stderr, "%s", usage);
127  fprintf(stderr, "invalid -video_size\n");
128  goto end;
129  }
130 
131  if (inFormat == AV_PIX_FMT_NONE) {
132  fprintf(stderr, "%s", usage);
133  fprintf(stderr, "invalid input pixel format\n");
134  goto end;
135  }
136 
137  desc = av_pix_fmt_desc_get(inFormat);
138  if (!(desc->flags & AV_PIX_FMT_FLAG_FLOAT)) {
139  fprintf(stderr, "input pixel format not floating point.\n");
140  goto end;
141  }
142 
143  res = av_image_fill_linesizes(rgbStride, inFormat, w);
144  if (res < 0) {
145  fprintf(stderr, "av_image_fill_linesizes failed\n");
146  goto end;
147  }
148  for (p = 0; p < 4; p++) {
149  rgbStride[p] = FFALIGN(rgbStride[p], 16);
150  if (rgbStride[p]) {
151  rgbIn[p] = av_mallocz(rgbStride[p] * h + 16);
152  rgbOut[p] = av_mallocz(rgbStride[p] * h + 16);
153  }
154  if (rgbStride[p] && (!rgbIn[p] || !rgbOut[p])) {
155  goto end;
156  }
157  }
158 
159  for (i = 0; i < FF_ARRAY_ELEMS(pix_fmts); i++) {
160  dstFormat = pix_fmts[i];
161  if (fp) {
162  fseek(fp, 0, SEEK_SET);
163  for (p = 0; p < 4; p++) {
164  if (!rgbStride[p])
165  continue;
166 
167  ptr = rgbIn[p];
168  for (y = 0; y < h; y++) {
169  size = fread(ptr, 1, w*4, fp);
170  if (size != w*4) {
171  fprintf(stderr, "read error: %d\n", size);
172  goto end;
173  }
174  ptr += rgbStride[p];
175  }
176  }
177  } else {
178  // fill src with random values between 0.0 - 1.0
179  av_lfg_init(&rand, 1);
180  for (p = 0; p < 4; p++) {
181  if (!rgbStride[p])
182  continue;
183 
184  for (y = 0; y < h; y++) {
185  in = (uint32_t*)(rgbIn[p] + y * rgbStride[p]);
186  for (x = 0; x < w; x++) {
187  v0.f = (float)av_lfg_get(&rand)/(float)(UINT32_MAX);
188  *in++ = AV_RL32(&v0.i);
189  }
190  }
191  }
192  }
193 
194  // setup intermediate image
195  for (p = 0; p < 4; p++) {
196  av_freep(&dst[p]);
197  }
198 
199  res = av_image_fill_linesizes(dstStride, dstFormat, w);
200  if (res < 0) {
201  fprintf(stderr, "av_image_fill_linesizes failed\n");
202  goto end;
203  }
204  for (p = 0; p < 4; p++) {
205  dstStride[p] = FFALIGN(dstStride[p], 16);
206  if (dstStride[p]) {
207  dst[p] = av_mallocz(dstStride[p] * h + 16);
208  }
209  if (dstStride[p] && !dst[p]) {
210  goto end;
211  }
212  }
213 
214  // srcFormat -> dstFormat
215  sws = sws_getContext(w, h, inFormat, w, h,
217  if (!sws) {
218  fprintf(stderr, "Failed to get %s -> %s\n", av_get_pix_fmt_name(inFormat), av_get_pix_fmt_name(dstFormat) );
219  goto end;
220  }
221 
222  res = sws_scale(sws, (const uint8_t *const *)rgbIn, rgbStride, 0, h, dst, dstStride);
223  if (res < 0 || res != h) {
224  fprintf(stderr, "sws_scale failed\n");
225  res = -1;
226  goto end;
227  }
228  sws_freeContext(sws);
229 
230  // dstFormat -> srcFormat
231  sws = sws_getContext(w, h, dstFormat, w, h,
232  inFormat, SWS_BILINEAR, NULL, NULL, NULL);
233  if(!sws) {
234  fprintf(stderr, "Failed to get %s -> %s\n", av_get_pix_fmt_name(dstFormat), av_get_pix_fmt_name(inFormat) );
235  goto end;
236  }
237 
238  res = sws_scale(sws, (const uint8_t *const *)dst, dstStride, 0, h, rgbOut, rgbStride);
239  if (res < 0 || res != h) {
240  fprintf(stderr, "sws_scale failed\n");
241  res = -1;
242  goto end;
243  }
244  sws_freeContext(sws);
245  sws = NULL;
246 
247  minimum = FLT_MAX;
248  maximum = -FLT_MAX;
249  count = 0;
250  sum = 0.0;
251 
252  for (p = 0; p < 4; p++) {
253  if (!rgbStride[p])
254  continue;
255 
256  for (y = 0; y < h; y++) {
257  in = (uint32_t*)(rgbIn[p] + y * rgbStride[p]);
258  out = (uint32_t*)(rgbOut[p] + y * rgbStride[p]);
259  for (x = 0; x < w; x++) {
260  if (desc->flags & AV_PIX_FMT_FLAG_BE) {
261  v0.i = AV_RB32(in);
262  v1.i = AV_RB32(out);
263  } else {
264  v0.i = AV_RL32(in);
265  v1.i = AV_RL32(out);
266  }
267 
268  diff = fabsf(v0.f - v1.f);
269  sum += diff;
271  maximum = FFMAX(maximum, diff);
272 
273  count++;
274  in++;
275  out++;
276  }
277  }
278  }
279 
280  fprintf(stdout, "%s -> %s -> %s\n", av_get_pix_fmt_name(inFormat), av_get_pix_fmt_name(dstFormat), av_get_pix_fmt_name(inFormat) );
281  fprintf(stdout, "avg diff: %f\nmin diff: %f\nmax diff: %f\n", sum / count, minimum, maximum);
282  res = 0;
283  }
284 
285 end:
286  sws_freeContext(sws);
287  for (p = 0; p < 4; p++) {
288  av_freep(&rgbIn[p]);
289  av_freep(&rgbOut[p]);
290  av_freep(&dst[p]);
291  }
292  if (fp)
293  fclose(fp);
294 
295  return res;
296 }
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
AV_PIX_FMT_BGR48LE
@ AV_PIX_FMT_BGR48LE
packed RGB 16:16:16, 48bpp, 16B, 16G, 16R, the 2-byte value for each R/G/B component is stored as lit...
Definition: pixfmt.h:139
out
FILE * out
Definition: movenc.c:54
av_lfg_init
av_cold void av_lfg_init(AVLFG *c, unsigned int seed)
Definition: lfg.c:32
main
int main(int argc, char **argv)
Definition: floatimg_cmp.c:62
av_pix_fmt_desc_get
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2541
AV_PIX_FMT_FLAG_FLOAT
#define AV_PIX_FMT_FLAG_FLOAT
The pixel format contains IEEE-754 floating point values.
Definition: pixdesc.h:159
pixdesc.h
w
uint8_t w
Definition: llviddspenc.c:39
av_intfloat32::i
uint32_t i
Definition: intfloat.h:28
DEFAULT_H
#define DEFAULT_H
Definition: floatimg_cmp.c:38
float.h
AV_PIX_FMT_BGR24
@ AV_PIX_FMT_BGR24
packed RGB 8:8:8, 24bpp, BGRBGR...
Definition: pixfmt.h:69
AV_PIX_FMT_BGRA
@ AV_PIX_FMT_BGRA
packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
Definition: pixfmt.h:95
sws_scale
int attribute_align_arg sws_scale(struct SwsContext *c, const uint8_t *const srcSlice[], const int srcStride[], int srcSliceY, int srcSliceH, uint8_t *const dst[], const int dstStride[])
swscale wrapper, so we don't need to export the SwsContext.
Definition: swscale.c:745
intfloat.h
AV_PIX_FMT_YUV444P16LE
@ AV_PIX_FMT_YUV444P16LE
planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
Definition: pixfmt.h:125
AV_PIX_FMT_GBRAP12LE
@ AV_PIX_FMT_GBRAP12LE
planar GBR 4:4:4:4 48bpp, little-endian
Definition: pixfmt.h:278
AV_PIX_FMT_GBRAP
@ AV_PIX_FMT_GBRAP
planar GBRA 4:4:4:4 32bpp
Definition: pixfmt.h:205
v0
#define v0
Definition: regdef.h:26
fabsf
static __device__ float fabsf(float a)
Definition: cuda_runtime.h:181
DEFAULT_W
#define DEFAULT_W
Definition: floatimg_cmp.c:37
AV_PIX_FMT_YUV444P12LE
@ AV_PIX_FMT_YUV444P12LE
planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
Definition: pixfmt.h:241
AV_PIX_FMT_YUV444P14LE
@ AV_PIX_FMT_YUV444P14LE
planar YUV 4:4:4,42bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
Definition: pixfmt.h:243
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
av_image_fill_linesizes
int av_image_fill_linesizes(int linesizes[4], enum AVPixelFormat pix_fmt, int width)
Fill plane linesizes for an image with pixel format pix_fmt and width width.
Definition: imgutils.c:89
intreadwrite.h
AV_PIX_FMT_GBRP16LE
@ AV_PIX_FMT_GBRP16LE
planar GBR 4:4:4 48bpp, little-endian
Definition: pixfmt.h:165
av_lfg_get
static unsigned int av_lfg_get(AVLFG *c)
Get the next random unsigned 32-bit number using an ALFG.
Definition: lfg.h:53
lfg.h
AV_PIX_FMT_GBRP12LE
@ AV_PIX_FMT_GBRP12LE
planar GBR 4:4:4 36bpp, little-endian
Definition: pixfmt.h:245
AV_PIX_FMT_GBRP10LE
@ AV_PIX_FMT_GBRP10LE
planar GBR 4:4:4 30bpp, little-endian
Definition: pixfmt.h:163
AV_PIX_FMT_RGBA
@ AV_PIX_FMT_RGBA
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
Definition: pixfmt.h:93
SwsContext::dstFormat
enum AVPixelFormat dstFormat
Destination pixel format.
Definition: swscale_internal.h:303
AV_PIX_FMT_YUV444P10LE
@ AV_PIX_FMT_YUV444P10LE
planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
Definition: pixfmt.h:155
NULL
#define NULL
Definition: coverity.c:32
AV_PIX_FMT_RGB48LE
@ AV_PIX_FMT_RGB48LE
packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, the 2-byte value for each R/G/B component is stored as lit...
Definition: pixfmt.h:103
AV_PIX_FMT_RGBA64LE
@ AV_PIX_FMT_RGBA64LE
packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is st...
Definition: pixfmt.h:196
parseutils.h
AV_PIX_FMT_BGR0
@ AV_PIX_FMT_BGR0
packed BGR 8:8:8, 32bpp, BGRXBGRX... X=unused/undefined
Definition: pixfmt.h:230
av_intfloat32
Definition: intfloat.h:27
fp
#define fp
Definition: regdef.h:44
AV_PIX_FMT_ABGR
@ AV_PIX_FMT_ABGR
packed ABGR 8:8:8:8, 32bpp, ABGRABGR...
Definition: pixfmt.h:94
usage
const char * usage
Definition: floatimg_cmp.c:60
AVLFG
Context structure for the Lagged Fibonacci PRNG.
Definition: lfg.h:33
minimum
static float minimum(float src0, float src1)
Definition: dnn_backend_native_layer_mathbinary.c:48
AV_PIX_FMT_RGB24
@ AV_PIX_FMT_RGB24
packed RGB 8:8:8, 24bpp, RGBRGB...
Definition: pixfmt.h:68
SwsFilterDescriptor::dst
SwsSlice * dst
Output slice.
Definition: swscale_internal.h:1004
sws_getContext
struct SwsContext * sws_getContext(int srcW, int srcH, enum AVPixelFormat srcFormat, int dstW, int dstH, enum AVPixelFormat dstFormat, int flags, SwsFilter *srcFilter, SwsFilter *dstFilter, const double *param)
Allocate and return an SwsContext.
Definition: utils.c:1910
FFMAX
#define FFMAX(a, b)
Definition: common.h:103
size
int size
Definition: twinvq_data.h:10344
AV_RB32
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_WL16 uint64_t_TMPL AV_WB64 unsigned int_TMPL AV_RB32
Definition: bytestream.h:96
AV_PIX_FMT_GBRP9LE
@ AV_PIX_FMT_GBRP9LE
planar GBR 4:4:4 27bpp, little-endian
Definition: pixfmt.h:161
FFMIN
#define FFMIN(a, b)
Definition: common.h:105
AV_PIX_FMT_GBRAP10LE
@ AV_PIX_FMT_GBRAP10LE
planar GBR 4:4:4:4 40bpp, little-endian
Definition: pixfmt.h:281
AV_PIX_FMT_RGB0
@ AV_PIX_FMT_RGB0
packed RGB 8:8:8, 32bpp, RGBXRGBX... X=unused/undefined
Definition: pixfmt.h:228
av_parse_video_size
int av_parse_video_size(int *width_ptr, int *height_ptr, const char *str)
Parse str and put in width_ptr and height_ptr the detected values.
Definition: parseutils.c:148
AV_PIX_FMT_ARGB
@ AV_PIX_FMT_ARGB
packed ARGB 8:8:8:8, 32bpp, ARGBARGB...
Definition: pixfmt.h:92
AV_PIX_FMT_BGRA64LE
@ AV_PIX_FMT_BGRA64LE
packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is st...
Definition: pixfmt.h:198
i
int i
Definition: input.c:407
AV_PIX_FMT_FLAG_BE
#define AV_PIX_FMT_FLAG_BE
Pixel format is big-endian.
Definition: pixdesc.h:117
av_mallocz
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:243
AV_PIX_FMT_GBRPF32LE
@ AV_PIX_FMT_GBRPF32LE
IEEE-754 single precision planar GBR 4:4:4, 96bpp, little-endian.
Definition: pixfmt.h:309
AV_PIX_FMT_GBRAP16LE
@ AV_PIX_FMT_GBRAP16LE
planar GBRA 4:4:4:4 64bpp, little-endian
Definition: pixfmt.h:207
AV_PIX_FMT_0BGR
@ AV_PIX_FMT_0BGR
packed BGR 8:8:8, 32bpp, XBGRXBGR... X=unused/undefined
Definition: pixfmt.h:229
AV_RL32
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_RL32
Definition: bytestream.h:92
av_get_pix_fmt
enum AVPixelFormat av_get_pix_fmt(const char *name)
Return the pixel format corresponding to name.
Definition: pixdesc.c:2473
sws_freeContext
void sws_freeContext(struct SwsContext *swsContext)
Free the swscaler context swsContext.
Definition: utils.c:2241
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:65
AV_PIX_FMT_YUV444P9LE
@ AV_PIX_FMT_YUV444P9LE
planar YUV 4:4:4, 27bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
Definition: pixfmt.h:153
AV_PIX_FMT_YUV444P
@ AV_PIX_FMT_YUV444P
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
Definition: pixfmt.h:71
av_intfloat32::f
float f
Definition: intfloat.h:29
AV_PIX_FMT_GBRP
@ AV_PIX_FMT_GBRP
planar GBR 4:4:4 24bpp
Definition: pixfmt.h:158
desc
const char * desc
Definition: libsvtav1.c:79
avutil.h
mem.h
AVPixFmtDescriptor
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:70
diff
static av_always_inline int diff(const uint32_t a, const uint32_t b)
Definition: vf_palettegen.c:136
FFALIGN
#define FFALIGN(x, a)
Definition: macros.h:48
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
AV_PIX_FMT_GBRP14LE
@ AV_PIX_FMT_GBRP14LE
planar GBR 4:4:4 42bpp, little-endian
Definition: pixfmt.h:247
imgutils.h
AV_PIX_FMT_0RGB
@ AV_PIX_FMT_0RGB
packed RGB 8:8:8, 32bpp, XRGBXRGB... X=unused/undefined
Definition: pixfmt.h:227
h
h
Definition: vp9dsp_template.c:2038
SWS_BILINEAR
#define SWS_BILINEAR
Definition: swscale.h:59
SwsContext
Definition: swscale_internal.h:283
pix_fmts
static enum AVPixelFormat pix_fmts[]
Definition: floatimg_cmp.c:40
swscale.h
av_get_pix_fmt_name
const char * av_get_pix_fmt_name(enum AVPixelFormat pix_fmt)
Return the short name for a pixel format, NULL in case pix_fmt is unknown.
Definition: pixdesc.c:2461