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,
216  dstFormat, SWS_BILINEAR, NULL, NULL, NULL);
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;
270  minimum = FFMIN(minimum, 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 }
Context structure for the Lagged Fibonacci PRNG.
Definition: lfg.h:33
planar GBR 4:4:4:4 40bpp, little-endian
Definition: pixfmt.h:291
#define NULL
Definition: coverity.c:32
ptrdiff_t const GLvoid GLenum usage
Definition: opengl_enc.c:100
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2573
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
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:208
const char * desc
Definition: libsvtav1.c:79
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
Definition: pixfmt.h:71
misc image utilities
packed RGB 8:8:8, 24bpp, RGBRGB...
Definition: pixfmt.h:68
Memory handling functions.
planar GBR 4:4:4 24bpp
Definition: pixfmt.h:168
int main(int argc, char **argv)
Definition: floatimg_cmp.c:62
Convenience header that includes libavutil&#39;s core.
planar GBR 4:4:4 36bpp, little-endian
Definition: pixfmt.h:255
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:237
packed BGR 8:8:8, 32bpp, XBGRXBGR... X=unused/undefined
Definition: pixfmt.h:239
#define SWS_BILINEAR
Definition: swscale.h:59
#define DEFAULT_H
Definition: floatimg_cmp.c:38
uint8_t
packed RGB 8:8:8, 32bpp, RGBXRGBX... X=unused/undefined
Definition: pixfmt.h:238
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
#define AV_PIX_FMT_FLAG_FLOAT
The pixel format contains IEEE-754 floating point values.
Definition: pixdesc.h:190
static av_cold int end(AVCodecContext *avctx)
Definition: avrndec.c:92
planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
Definition: pixfmt.h:251
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:91
packed ABGR 8:8:8:8, 32bpp, ABGRABGR...
Definition: pixfmt.h:94
SwsSlice * dst
Output slice.
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:1917
external API header
ptrdiff_t size
Definition: opengl_enc.c:100
static __device__ float fabsf(float a)
Definition: cuda_runtime.h:181
#define FFALIGN(x, a)
Definition: macros.h:48
#define DEFAULT_W
Definition: floatimg_cmp.c:37
planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
Definition: pixfmt.h:165
packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
Definition: pixfmt.h:95
GLsizei count
Definition: opengl_enc.c:108
#define FFMAX(a, b)
Definition: common.h:94
packed ARGB 8:8:8:8, 32bpp, ARGBARGB...
Definition: pixfmt.h:92
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:149
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
Definition: pixfmt.h:93
uint64_t flags
Combination of AV_PIX_FMT_FLAG_...
Definition: pixdesc.h:106
IEEE-754 single precision planar GBR 4:4:4, 96bpp, little-endian.
Definition: pixfmt.h:319
#define FFMIN(a, b)
Definition: common.h:96
static float minimum(float src0, float src1)
uint8_t w
Definition: llviddspenc.c:38
void sws_freeContext(struct SwsContext *swsContext)
Free the swscaler context swsContext.
Definition: utils.c:2337
uint32_t i
Definition: intfloat.h:28
packed RGB 8:8:8, 24bpp, BGRBGR...
Definition: pixfmt.h:69
#define FF_ARRAY_ELEMS(a)
planar GBR 4:4:4:4 48bpp, little-endian
Definition: pixfmt.h:288
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:81
#define fp
Definition: regdef.h:44
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&#39;t need to export the SwsContext.
Definition: swscale.c:744
static unsigned int av_lfg_get(AVLFG *c)
Get the next random unsigned 32-bit number using an ALFG.
Definition: lfg.h:53
planar GBR 4:4:4 42bpp, little-endian
Definition: pixfmt.h:257
uint8_t pi<< 24) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi-0x80)*(1.0f/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi-0x80)*(1.0/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t,(*(const int16_t *) pi >> 8)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t,*(const int16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t,*(const int16_t *) pi *(1.0/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t,(*(const int32_t *) pi >> 24)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t,*(const int32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t,*(const int32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8(lrintf(*(const float *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16(lrintf(*(const float *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(const float *) pi *(1U<< 31)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8(lrint(*(const double *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16(lrint(*(const double *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(const double *) pi *(1U<< 31))))#define SET_CONV_FUNC_GROUP(ofmt, ifmt) static void set_generic_function(AudioConvert *ac){}void ff_audio_convert_free(AudioConvert **ac){if(!*ac) return;ff_dither_free(&(*ac) ->dc);av_freep(ac);}AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, int sample_rate, int apply_map){AudioConvert *ac;int in_planar, out_planar;ac=av_mallocz(sizeof(*ac));if(!ac) return NULL;ac->avr=avr;ac->out_fmt=out_fmt;ac->in_fmt=in_fmt;ac->channels=channels;ac->apply_map=apply_map;if(avr->dither_method!=AV_RESAMPLE_DITHER_NONE &&av_get_packed_sample_fmt(out_fmt)==AV_SAMPLE_FMT_S16 &&av_get_bytes_per_sample(in_fmt) > 2){ac->dc=ff_dither_alloc(avr, out_fmt, in_fmt, channels, sample_rate, apply_map);if(!ac->dc){av_free(ac);return NULL;}return ac;}in_planar=ff_sample_fmt_is_planar(in_fmt, channels);out_planar=ff_sample_fmt_is_planar(out_fmt, channels);if(in_planar==out_planar){ac->func_type=CONV_FUNC_TYPE_FLAT;ac->planes=in_planar?ac->channels:1;}else if(in_planar) ac->func_type=CONV_FUNC_TYPE_INTERLEAVE;else ac->func_type=CONV_FUNC_TYPE_DEINTERLEAVE;set_generic_function(ac);if(ARCH_AARCH64) ff_audio_convert_init_aarch64(ac);if(ARCH_ARM) ff_audio_convert_init_arm(ac);if(ARCH_X86) ff_audio_convert_init_x86(ac);return ac;}int ff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in){int use_generic=1;int len=in->nb_samples;int p;if(ac->dc){av_log(ac->avr, AV_LOG_TRACE,"%d samples - audio_convert: %s to %s (dithered)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt));return ff_convert_dither(ac-> in
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
packed BGR 8:8:8, 32bpp, BGRXBGRX... X=unused/undefined
Definition: pixfmt.h:240
av_cold void av_lfg_init(AVLFG *c, unsigned int seed)
Definition: lfg.c:32
misc parsing utilities
planar YUV 4:4:4, 27bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
Definition: pixfmt.h:163
planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
Definition: pixfmt.h:135
planar GBRA 4:4:4:4 32bpp
Definition: pixfmt.h:215
planar GBR 4:4:4 27bpp, little-endian
Definition: pixfmt.h:171
#define AV_PIX_FMT_FLAG_BE
Pixel format is big-endian.
Definition: pixdesc.h:128
static av_always_inline int diff(const uint32_t a, const uint32_t b)
planar YUV 4:4:4,42bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
Definition: pixfmt.h:253
static enum AVPixelFormat pix_fmts[]
Definition: floatimg_cmp.c:40
FILE * out
Definition: movenc.c:54
#define av_freep(p)
planar GBR 4:4:4 48bpp, little-endian
Definition: pixfmt.h:175
enum AVPixelFormat av_get_pix_fmt(const char *name)
Return the pixel format corresponding to name.
Definition: pixdesc.c:2501
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:2489
planar GBRA 4:4:4:4 64bpp, little-endian
Definition: pixfmt.h:217
packed RGB 8:8:8, 32bpp, XRGBXRGB... X=unused/undefined
Definition: pixfmt.h:237
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_RL32
Definition: bytestream.h:91
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
int i
Definition: input.c:407
planar GBR 4:4:4 30bpp, little-endian
Definition: pixfmt.h:173
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:206