1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * This file is part of FFmpeg. 3cabdff1aSopenharmony_ci * 4cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 5cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 6cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 7cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 8cabdff1aSopenharmony_ci * 9cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 10cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 11cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12cabdff1aSopenharmony_ci * Lesser General Public License for more details. 13cabdff1aSopenharmony_ci * 14cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 15cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 16cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17cabdff1aSopenharmony_ci */ 18cabdff1aSopenharmony_ci 19cabdff1aSopenharmony_ci#include <stdio.h> 20cabdff1aSopenharmony_ci#include <stdlib.h> 21cabdff1aSopenharmony_ci#include <string.h> 22cabdff1aSopenharmony_ci#include <math.h> 23cabdff1aSopenharmony_ci#include <inttypes.h> 24cabdff1aSopenharmony_ci#include <float.h> 25cabdff1aSopenharmony_ci 26cabdff1aSopenharmony_ci#include "libavutil/avutil.h" 27cabdff1aSopenharmony_ci#include "libavutil/imgutils.h" 28cabdff1aSopenharmony_ci#include "libavutil/intfloat.h" 29cabdff1aSopenharmony_ci#include "libavutil/intreadwrite.h" 30cabdff1aSopenharmony_ci#include "libavutil/lfg.h" 31cabdff1aSopenharmony_ci#include "libavutil/mem.h" 32cabdff1aSopenharmony_ci#include "libavutil/parseutils.h" 33cabdff1aSopenharmony_ci#include "libavutil/pixdesc.h" 34cabdff1aSopenharmony_ci 35cabdff1aSopenharmony_ci#include "libswscale/swscale.h" 36cabdff1aSopenharmony_ci 37cabdff1aSopenharmony_ci#define DEFAULT_W 96 38cabdff1aSopenharmony_ci#define DEFAULT_H 96 39cabdff1aSopenharmony_ci 40cabdff1aSopenharmony_cistatic const enum AVPixelFormat pix_fmts[] = { 41cabdff1aSopenharmony_ci AV_PIX_FMT_YUV444P16LE, 42cabdff1aSopenharmony_ci AV_PIX_FMT_YUV444P, 43cabdff1aSopenharmony_ci AV_PIX_FMT_YUV444P9LE, AV_PIX_FMT_YUV444P10LE, 44cabdff1aSopenharmony_ci AV_PIX_FMT_YUV444P12LE, AV_PIX_FMT_YUV444P14LE, 45cabdff1aSopenharmony_ci AV_PIX_FMT_RGB24, AV_PIX_FMT_BGR24, 46cabdff1aSopenharmony_ci AV_PIX_FMT_RGBA, AV_PIX_FMT_BGRA, 47cabdff1aSopenharmony_ci AV_PIX_FMT_ARGB, AV_PIX_FMT_ABGR, 48cabdff1aSopenharmony_ci AV_PIX_FMT_0RGB, AV_PIX_FMT_0BGR, 49cabdff1aSopenharmony_ci AV_PIX_FMT_RGB0, AV_PIX_FMT_BGR0, 50cabdff1aSopenharmony_ci AV_PIX_FMT_RGB48LE, AV_PIX_FMT_BGR48LE, 51cabdff1aSopenharmony_ci AV_PIX_FMT_RGBA64LE, AV_PIX_FMT_BGRA64LE, 52cabdff1aSopenharmony_ci AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP, 53cabdff1aSopenharmony_ci AV_PIX_FMT_GBRP9LE, 54cabdff1aSopenharmony_ci AV_PIX_FMT_GBRP10LE, AV_PIX_FMT_GBRAP10LE, 55cabdff1aSopenharmony_ci AV_PIX_FMT_GBRP12LE, AV_PIX_FMT_GBRAP12LE, 56cabdff1aSopenharmony_ci AV_PIX_FMT_GBRP14LE, 57cabdff1aSopenharmony_ci AV_PIX_FMT_GBRP16LE, AV_PIX_FMT_GBRAP16LE 58cabdff1aSopenharmony_ci}; 59cabdff1aSopenharmony_ci 60cabdff1aSopenharmony_ciconst char *usage = "floatimg_cmp -pixel_format <pix_fmt> -size <image_size> -ref <testfile>\n"; 61cabdff1aSopenharmony_ci 62cabdff1aSopenharmony_ciint main(int argc, char **argv) 63cabdff1aSopenharmony_ci{ 64cabdff1aSopenharmony_ci enum AVPixelFormat inFormat = AV_PIX_FMT_NONE; 65cabdff1aSopenharmony_ci enum AVPixelFormat dstFormat = AV_PIX_FMT_NONE; 66cabdff1aSopenharmony_ci const AVPixFmtDescriptor *desc; 67cabdff1aSopenharmony_ci uint8_t *ptr; 68cabdff1aSopenharmony_ci uint32_t *in, *out; 69cabdff1aSopenharmony_ci 70cabdff1aSopenharmony_ci uint8_t *rgbIn[4] = {NULL, NULL, NULL, NULL}; 71cabdff1aSopenharmony_ci uint8_t *rgbOut[4] = {NULL, NULL, NULL, NULL}; 72cabdff1aSopenharmony_ci int rgbStride[4]; 73cabdff1aSopenharmony_ci 74cabdff1aSopenharmony_ci uint8_t *dst[4] = {NULL, NULL, NULL, NULL}; 75cabdff1aSopenharmony_ci int dstStride[4]; 76cabdff1aSopenharmony_ci 77cabdff1aSopenharmony_ci int i, x, y, p, size, count; 78cabdff1aSopenharmony_ci int res = -1; 79cabdff1aSopenharmony_ci int w = -1; 80cabdff1aSopenharmony_ci int h = -1; 81cabdff1aSopenharmony_ci union av_intfloat32 v0, v1; 82cabdff1aSopenharmony_ci 83cabdff1aSopenharmony_ci double sum; 84cabdff1aSopenharmony_ci float minimum, maximum, diff; 85cabdff1aSopenharmony_ci 86cabdff1aSopenharmony_ci struct SwsContext *sws = NULL; 87cabdff1aSopenharmony_ci AVLFG rand; 88cabdff1aSopenharmony_ci FILE *fp = NULL; 89cabdff1aSopenharmony_ci 90cabdff1aSopenharmony_ci for (i = 1; i < argc; i += 2) { 91cabdff1aSopenharmony_ci if (argv[i][0] != '-' || i + 1 == argc) 92cabdff1aSopenharmony_ci goto bad_option; 93cabdff1aSopenharmony_ci if (!strcmp(argv[i], "-ref")) { 94cabdff1aSopenharmony_ci fp = fopen(argv[i + 1], "rb"); 95cabdff1aSopenharmony_ci if (!fp) { 96cabdff1aSopenharmony_ci fprintf(stderr, "could not open '%s'\n", argv[i + 1]); 97cabdff1aSopenharmony_ci goto end; 98cabdff1aSopenharmony_ci } 99cabdff1aSopenharmony_ci } else if (!strcmp(argv[i], "-size")) { 100cabdff1aSopenharmony_ci res = av_parse_video_size(&w, &h, argv[i + 1]); 101cabdff1aSopenharmony_ci if (res < 0) { 102cabdff1aSopenharmony_ci fprintf(stderr, "invalid video size %s\n", argv[i + 1]); 103cabdff1aSopenharmony_ci goto end; 104cabdff1aSopenharmony_ci } 105cabdff1aSopenharmony_ci } else if (!strcmp(argv[i], "-pixel_format")) { 106cabdff1aSopenharmony_ci inFormat = av_get_pix_fmt(argv[i + 1]); 107cabdff1aSopenharmony_ci if (inFormat == AV_PIX_FMT_NONE) { 108cabdff1aSopenharmony_ci fprintf(stderr, "invalid pixel format %s\n", argv[i + 1]); 109cabdff1aSopenharmony_ci goto end; 110cabdff1aSopenharmony_ci } 111cabdff1aSopenharmony_ci } else { 112cabdff1aSopenharmony_cibad_option: 113cabdff1aSopenharmony_ci fprintf(stderr, "%s", usage); 114cabdff1aSopenharmony_ci fprintf(stderr, "bad option or argument missing (%s)\n", argv[i]); 115cabdff1aSopenharmony_ci goto end; 116cabdff1aSopenharmony_ci }; 117cabdff1aSopenharmony_ci } 118cabdff1aSopenharmony_ci 119cabdff1aSopenharmony_ci if (!fp) { 120cabdff1aSopenharmony_ci inFormat = AV_PIX_FMT_GBRPF32LE; 121cabdff1aSopenharmony_ci w = DEFAULT_W; 122cabdff1aSopenharmony_ci h = DEFAULT_H; 123cabdff1aSopenharmony_ci } 124cabdff1aSopenharmony_ci 125cabdff1aSopenharmony_ci if (w <= 0 || h <= 0) { 126cabdff1aSopenharmony_ci fprintf(stderr, "%s", usage); 127cabdff1aSopenharmony_ci fprintf(stderr, "invalid -video_size\n"); 128cabdff1aSopenharmony_ci goto end; 129cabdff1aSopenharmony_ci } 130cabdff1aSopenharmony_ci 131cabdff1aSopenharmony_ci if (inFormat == AV_PIX_FMT_NONE) { 132cabdff1aSopenharmony_ci fprintf(stderr, "%s", usage); 133cabdff1aSopenharmony_ci fprintf(stderr, "invalid input pixel format\n"); 134cabdff1aSopenharmony_ci goto end; 135cabdff1aSopenharmony_ci } 136cabdff1aSopenharmony_ci 137cabdff1aSopenharmony_ci desc = av_pix_fmt_desc_get(inFormat); 138cabdff1aSopenharmony_ci if (!(desc->flags & AV_PIX_FMT_FLAG_FLOAT)) { 139cabdff1aSopenharmony_ci fprintf(stderr, "input pixel format not floating point.\n"); 140cabdff1aSopenharmony_ci goto end; 141cabdff1aSopenharmony_ci } 142cabdff1aSopenharmony_ci 143cabdff1aSopenharmony_ci res = av_image_fill_linesizes(rgbStride, inFormat, w); 144cabdff1aSopenharmony_ci if (res < 0) { 145cabdff1aSopenharmony_ci fprintf(stderr, "av_image_fill_linesizes failed\n"); 146cabdff1aSopenharmony_ci goto end; 147cabdff1aSopenharmony_ci } 148cabdff1aSopenharmony_ci for (p = 0; p < 4; p++) { 149cabdff1aSopenharmony_ci rgbStride[p] = FFALIGN(rgbStride[p], 16); 150cabdff1aSopenharmony_ci if (rgbStride[p]) { 151cabdff1aSopenharmony_ci rgbIn[p] = av_mallocz(rgbStride[p] * h + 16); 152cabdff1aSopenharmony_ci rgbOut[p] = av_mallocz(rgbStride[p] * h + 16); 153cabdff1aSopenharmony_ci } 154cabdff1aSopenharmony_ci if (rgbStride[p] && (!rgbIn[p] || !rgbOut[p])) { 155cabdff1aSopenharmony_ci goto end; 156cabdff1aSopenharmony_ci } 157cabdff1aSopenharmony_ci } 158cabdff1aSopenharmony_ci 159cabdff1aSopenharmony_ci for (i = 0; i < FF_ARRAY_ELEMS(pix_fmts); i++) { 160cabdff1aSopenharmony_ci dstFormat = pix_fmts[i]; 161cabdff1aSopenharmony_ci if (fp) { 162cabdff1aSopenharmony_ci fseek(fp, 0, SEEK_SET); 163cabdff1aSopenharmony_ci for (p = 0; p < 4; p++) { 164cabdff1aSopenharmony_ci if (!rgbStride[p]) 165cabdff1aSopenharmony_ci continue; 166cabdff1aSopenharmony_ci 167cabdff1aSopenharmony_ci ptr = rgbIn[p]; 168cabdff1aSopenharmony_ci for (y = 0; y < h; y++) { 169cabdff1aSopenharmony_ci size = fread(ptr, 1, w*4, fp); 170cabdff1aSopenharmony_ci if (size != w*4) { 171cabdff1aSopenharmony_ci fprintf(stderr, "read error: %d\n", size); 172cabdff1aSopenharmony_ci goto end; 173cabdff1aSopenharmony_ci } 174cabdff1aSopenharmony_ci ptr += rgbStride[p]; 175cabdff1aSopenharmony_ci } 176cabdff1aSopenharmony_ci } 177cabdff1aSopenharmony_ci } else { 178cabdff1aSopenharmony_ci // fill src with random values between 0.0 - 1.0 179cabdff1aSopenharmony_ci av_lfg_init(&rand, 1); 180cabdff1aSopenharmony_ci for (p = 0; p < 4; p++) { 181cabdff1aSopenharmony_ci if (!rgbStride[p]) 182cabdff1aSopenharmony_ci continue; 183cabdff1aSopenharmony_ci 184cabdff1aSopenharmony_ci for (y = 0; y < h; y++) { 185cabdff1aSopenharmony_ci in = (uint32_t*)(rgbIn[p] + y * rgbStride[p]); 186cabdff1aSopenharmony_ci for (x = 0; x < w; x++) { 187cabdff1aSopenharmony_ci v0.f = (float)av_lfg_get(&rand)/(float)(UINT32_MAX); 188cabdff1aSopenharmony_ci *in++ = AV_RL32(&v0.i); 189cabdff1aSopenharmony_ci } 190cabdff1aSopenharmony_ci } 191cabdff1aSopenharmony_ci } 192cabdff1aSopenharmony_ci } 193cabdff1aSopenharmony_ci 194cabdff1aSopenharmony_ci // setup intermediate image 195cabdff1aSopenharmony_ci for (p = 0; p < 4; p++) { 196cabdff1aSopenharmony_ci av_freep(&dst[p]); 197cabdff1aSopenharmony_ci } 198cabdff1aSopenharmony_ci 199cabdff1aSopenharmony_ci res = av_image_fill_linesizes(dstStride, dstFormat, w); 200cabdff1aSopenharmony_ci if (res < 0) { 201cabdff1aSopenharmony_ci fprintf(stderr, "av_image_fill_linesizes failed\n"); 202cabdff1aSopenharmony_ci goto end; 203cabdff1aSopenharmony_ci } 204cabdff1aSopenharmony_ci for (p = 0; p < 4; p++) { 205cabdff1aSopenharmony_ci dstStride[p] = FFALIGN(dstStride[p], 16); 206cabdff1aSopenharmony_ci if (dstStride[p]) { 207cabdff1aSopenharmony_ci dst[p] = av_mallocz(dstStride[p] * h + 16); 208cabdff1aSopenharmony_ci } 209cabdff1aSopenharmony_ci if (dstStride[p] && !dst[p]) { 210cabdff1aSopenharmony_ci goto end; 211cabdff1aSopenharmony_ci } 212cabdff1aSopenharmony_ci } 213cabdff1aSopenharmony_ci 214cabdff1aSopenharmony_ci // srcFormat -> dstFormat 215cabdff1aSopenharmony_ci sws = sws_getContext(w, h, inFormat, w, h, 216cabdff1aSopenharmony_ci dstFormat, SWS_BILINEAR, NULL, NULL, NULL); 217cabdff1aSopenharmony_ci if (!sws) { 218cabdff1aSopenharmony_ci fprintf(stderr, "Failed to get %s -> %s\n", av_get_pix_fmt_name(inFormat), av_get_pix_fmt_name(dstFormat) ); 219cabdff1aSopenharmony_ci goto end; 220cabdff1aSopenharmony_ci } 221cabdff1aSopenharmony_ci 222cabdff1aSopenharmony_ci res = sws_scale(sws, (const uint8_t *const *)rgbIn, rgbStride, 0, h, dst, dstStride); 223cabdff1aSopenharmony_ci if (res < 0 || res != h) { 224cabdff1aSopenharmony_ci fprintf(stderr, "sws_scale failed\n"); 225cabdff1aSopenharmony_ci res = -1; 226cabdff1aSopenharmony_ci goto end; 227cabdff1aSopenharmony_ci } 228cabdff1aSopenharmony_ci sws_freeContext(sws); 229cabdff1aSopenharmony_ci 230cabdff1aSopenharmony_ci // dstFormat -> srcFormat 231cabdff1aSopenharmony_ci sws = sws_getContext(w, h, dstFormat, w, h, 232cabdff1aSopenharmony_ci inFormat, SWS_BILINEAR, NULL, NULL, NULL); 233cabdff1aSopenharmony_ci if(!sws) { 234cabdff1aSopenharmony_ci fprintf(stderr, "Failed to get %s -> %s\n", av_get_pix_fmt_name(dstFormat), av_get_pix_fmt_name(inFormat) ); 235cabdff1aSopenharmony_ci goto end; 236cabdff1aSopenharmony_ci } 237cabdff1aSopenharmony_ci 238cabdff1aSopenharmony_ci res = sws_scale(sws, (const uint8_t *const *)dst, dstStride, 0, h, rgbOut, rgbStride); 239cabdff1aSopenharmony_ci if (res < 0 || res != h) { 240cabdff1aSopenharmony_ci fprintf(stderr, "sws_scale failed\n"); 241cabdff1aSopenharmony_ci res = -1; 242cabdff1aSopenharmony_ci goto end; 243cabdff1aSopenharmony_ci } 244cabdff1aSopenharmony_ci sws_freeContext(sws); 245cabdff1aSopenharmony_ci sws = NULL; 246cabdff1aSopenharmony_ci 247cabdff1aSopenharmony_ci minimum = FLT_MAX; 248cabdff1aSopenharmony_ci maximum = -FLT_MAX; 249cabdff1aSopenharmony_ci count = 0; 250cabdff1aSopenharmony_ci sum = 0.0; 251cabdff1aSopenharmony_ci 252cabdff1aSopenharmony_ci for (p = 0; p < 4; p++) { 253cabdff1aSopenharmony_ci if (!rgbStride[p]) 254cabdff1aSopenharmony_ci continue; 255cabdff1aSopenharmony_ci 256cabdff1aSopenharmony_ci for (y = 0; y < h; y++) { 257cabdff1aSopenharmony_ci in = (uint32_t*)(rgbIn[p] + y * rgbStride[p]); 258cabdff1aSopenharmony_ci out = (uint32_t*)(rgbOut[p] + y * rgbStride[p]); 259cabdff1aSopenharmony_ci for (x = 0; x < w; x++) { 260cabdff1aSopenharmony_ci if (desc->flags & AV_PIX_FMT_FLAG_BE) { 261cabdff1aSopenharmony_ci v0.i = AV_RB32(in); 262cabdff1aSopenharmony_ci v1.i = AV_RB32(out); 263cabdff1aSopenharmony_ci } else { 264cabdff1aSopenharmony_ci v0.i = AV_RL32(in); 265cabdff1aSopenharmony_ci v1.i = AV_RL32(out); 266cabdff1aSopenharmony_ci } 267cabdff1aSopenharmony_ci 268cabdff1aSopenharmony_ci diff = fabsf(v0.f - v1.f); 269cabdff1aSopenharmony_ci sum += diff; 270cabdff1aSopenharmony_ci minimum = FFMIN(minimum, diff); 271cabdff1aSopenharmony_ci maximum = FFMAX(maximum, diff); 272cabdff1aSopenharmony_ci 273cabdff1aSopenharmony_ci count++; 274cabdff1aSopenharmony_ci in++; 275cabdff1aSopenharmony_ci out++; 276cabdff1aSopenharmony_ci } 277cabdff1aSopenharmony_ci } 278cabdff1aSopenharmony_ci } 279cabdff1aSopenharmony_ci 280cabdff1aSopenharmony_ci fprintf(stdout, "%s -> %s -> %s\n", av_get_pix_fmt_name(inFormat), av_get_pix_fmt_name(dstFormat), av_get_pix_fmt_name(inFormat) ); 281cabdff1aSopenharmony_ci fprintf(stdout, "avg diff: %f\nmin diff: %f\nmax diff: %f\n", sum / count, minimum, maximum); 282cabdff1aSopenharmony_ci res = 0; 283cabdff1aSopenharmony_ci } 284cabdff1aSopenharmony_ci 285cabdff1aSopenharmony_ciend: 286cabdff1aSopenharmony_ci sws_freeContext(sws); 287cabdff1aSopenharmony_ci for (p = 0; p < 4; p++) { 288cabdff1aSopenharmony_ci av_freep(&rgbIn[p]); 289cabdff1aSopenharmony_ci av_freep(&rgbOut[p]); 290cabdff1aSopenharmony_ci av_freep(&dst[p]); 291cabdff1aSopenharmony_ci } 292cabdff1aSopenharmony_ci if (fp) 293cabdff1aSopenharmony_ci fclose(fp); 294cabdff1aSopenharmony_ci 295cabdff1aSopenharmony_ci return res; 296cabdff1aSopenharmony_ci} 297