tools_common.c 13.1 KB
Newer Older
John Koleszar's avatar
John Koleszar committed
1
/*
2
 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
John Koleszar's avatar
John Koleszar committed
3
 *
4 5 6 7 8 9
 * This source code is subject to the terms of the BSD 2 Clause License and
 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
 * was not distributed with this source code in the LICENSE file, you can
 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
 * Media Patent License 1.0 was not distributed with this source code in the
 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
John Koleszar's avatar
John Koleszar committed
10
 */
11

12
#include <math.h>
13
#include <stdarg.h>
14
#include <stdio.h>
15
#include <stdlib.h>
16
#include <string.h>
17

18 19
#include "./tools_common.h"

20
#if CONFIG_AV1_ENCODER
Adrian Grange's avatar
Adrian Grange committed
21
#include "aom/aomcx.h"
22 23
#endif

24
#if CONFIG_AV1_DECODER
Adrian Grange's avatar
Adrian Grange committed
25
#include "aom/aomdx.h"
26 27
#endif

John Koleszar's avatar
John Koleszar committed
28
#if defined(_WIN32) || defined(__OS2__)
John Koleszar's avatar
John Koleszar committed
29 30
#include <io.h>
#include <fcntl.h>
John Koleszar's avatar
John Koleszar committed
31 32

#ifdef __OS2__
clang-format's avatar
clang-format committed
33 34 35
#define _setmode setmode
#define _fileno fileno
#define _O_BINARY O_BINARY
John Koleszar's avatar
John Koleszar committed
36
#endif
John Koleszar's avatar
John Koleszar committed
37 38
#endif

clang-format's avatar
clang-format committed
39 40 41 42 43 44 45 46 47 48
#define LOG_ERROR(label)               \
  do {                                 \
    const char *l = label;             \
    va_list ap;                        \
    va_start(ap, fmt);                 \
    if (l) fprintf(stderr, "%s: ", l); \
    vfprintf(stderr, fmt, ap);         \
    fprintf(stderr, "\n");             \
    va_end(ap);                        \
  } while (0)
49

John Koleszar's avatar
John Koleszar committed
50 51
FILE *set_binary_mode(FILE *stream) {
  (void)stream;
John Koleszar's avatar
John Koleszar committed
52
#if defined(_WIN32) || defined(__OS2__)
John Koleszar's avatar
John Koleszar committed
53
  _setmode(_fileno(stream), _O_BINARY);
John Koleszar's avatar
John Koleszar committed
54
#endif
John Koleszar's avatar
John Koleszar committed
55
  return stream;
John Koleszar's avatar
John Koleszar committed
56
}
57 58 59 60 61 62 63 64 65 66 67

void die(const char *fmt, ...) {
  LOG_ERROR(NULL);
  usage_exit();
}

void fatal(const char *fmt, ...) {
  LOG_ERROR("Fatal");
  exit(EXIT_FAILURE);
}

clang-format's avatar
clang-format committed
68
void warn(const char *fmt, ...) { LOG_ERROR("Warning"); }
69

Adrian Grange's avatar
Adrian Grange committed
70 71
void die_codec(aom_codec_ctx_t *ctx, const char *s) {
  const char *detail = aom_codec_error_detail(ctx);
72

Adrian Grange's avatar
Adrian Grange committed
73
  printf("%s: %s\n", s, aom_codec_error(ctx));
clang-format's avatar
clang-format committed
74
  if (detail) printf("    %s\n", detail);
75 76 77
  exit(EXIT_FAILURE);
}

Adrian Grange's avatar
Adrian Grange committed
78
int read_yuv_frame(struct AvxInputContext *input_ctx, aom_image_t *yuv_frame) {
79 80 81 82
  FILE *f = input_ctx->file;
  struct FileTypeDetectionBuffer *detect = &input_ctx->detect;
  int plane = 0;
  int shortread = 0;
Adrian Grange's avatar
Adrian Grange committed
83
  const int bytespp = (yuv_frame->fmt & AOM_IMG_FMT_HIGHBITDEPTH) ? 2 : 1;
84 85 86

  for (plane = 0; plane < 3; ++plane) {
    uint8_t *ptr;
Adrian Grange's avatar
Adrian Grange committed
87 88
    const int w = aom_img_plane_width(yuv_frame, plane);
    const int h = aom_img_plane_height(yuv_frame, plane);
89 90 91 92 93 94 95 96
    int r;

    /* Determine the correct plane based on the image format. The for-loop
     * always counts in Y,U,V order, but this may not match the order of
     * the data on disk.
     */
    switch (plane) {
      case 1:
clang-format's avatar
clang-format committed
97
        ptr =
Adrian Grange's avatar
Adrian Grange committed
98 99
            yuv_frame->planes[yuv_frame->fmt == AOM_IMG_FMT_YV12 ? AOM_PLANE_V
                                                                 : AOM_PLANE_U];
100 101
        break;
      case 2:
clang-format's avatar
clang-format committed
102
        ptr =
Adrian Grange's avatar
Adrian Grange committed
103 104
            yuv_frame->planes[yuv_frame->fmt == AOM_IMG_FMT_YV12 ? AOM_PLANE_U
                                                                 : AOM_PLANE_V];
105
        break;
clang-format's avatar
clang-format committed
106
      default: ptr = yuv_frame->planes[plane];
107 108 109
    }

    for (r = 0; r < h; ++r) {
110
      size_t needed = w * bytespp;
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
      size_t buf_position = 0;
      const size_t left = detect->buf_read - detect->position;
      if (left > 0) {
        const size_t more = (left < needed) ? left : needed;
        memcpy(ptr, detect->buf + detect->position, more);
        buf_position = more;
        needed -= more;
        detect->position += more;
      }
      if (needed > 0) {
        shortread |= (fread(ptr + buf_position, 1, needed, f) < needed);
      }

      ptr += yuv_frame->stride[plane];
    }
  }

  return shortread;
}
130

131 132
#if CONFIG_ENCODERS

Adrian Grange's avatar
Adrian Grange committed
133
static const AvxInterface aom_encoders[] = {
134 135
#if CONFIG_AV1_ENCODER
  { "av1", AV1_FOURCC, &aom_codec_av1_cx },
136
#endif
137 138
};

Adrian Grange's avatar
Adrian Grange committed
139 140
int get_aom_encoder_count(void) {
  return sizeof(aom_encoders) / sizeof(aom_encoders[0]);
141 142
}

Adrian Grange's avatar
Adrian Grange committed
143
const AvxInterface *get_aom_encoder_by_index(int i) { return &aom_encoders[i]; }
144

Adrian Grange's avatar
Adrian Grange committed
145
const AvxInterface *get_aom_encoder_by_name(const char *name) {
146 147
  int i;

Adrian Grange's avatar
Adrian Grange committed
148
  for (i = 0; i < get_aom_encoder_count(); ++i) {
Adrian Grange's avatar
Adrian Grange committed
149
    const AvxInterface *encoder = get_aom_encoder_by_index(i);
clang-format's avatar
clang-format committed
150
    if (strcmp(encoder->name, name) == 0) return encoder;
151 152 153 154 155
  }

  return NULL;
}

156 157 158 159
#endif  // CONFIG_ENCODERS

#if CONFIG_DECODERS

Adrian Grange's avatar
Adrian Grange committed
160
static const AvxInterface aom_decoders[] = {
161 162
#if CONFIG_AV1_DECODER
  { "av1", AV1_FOURCC, &aom_codec_av1_dx },
Jingning Han's avatar
Jingning Han committed
163
#endif
164 165
};

Adrian Grange's avatar
Adrian Grange committed
166 167
int get_aom_decoder_count(void) {
  return sizeof(aom_decoders) / sizeof(aom_decoders[0]);
168 169
}

Adrian Grange's avatar
Adrian Grange committed
170
const AvxInterface *get_aom_decoder_by_index(int i) { return &aom_decoders[i]; }
171

Adrian Grange's avatar
Adrian Grange committed
172
const AvxInterface *get_aom_decoder_by_name(const char *name) {
173 174
  int i;

Adrian Grange's avatar
Adrian Grange committed
175
  for (i = 0; i < get_aom_decoder_count(); ++i) {
Adrian Grange's avatar
Adrian Grange committed
176
    const AvxInterface *const decoder = get_aom_decoder_by_index(i);
clang-format's avatar
clang-format committed
177
    if (strcmp(decoder->name, name) == 0) return decoder;
178
  }
179 180 181 182

  return NULL;
}

Adrian Grange's avatar
Adrian Grange committed
183
const AvxInterface *get_aom_decoder_by_fourcc(uint32_t fourcc) {
184 185
  int i;

Adrian Grange's avatar
Adrian Grange committed
186
  for (i = 0; i < get_aom_decoder_count(); ++i) {
Adrian Grange's avatar
Adrian Grange committed
187
    const AvxInterface *const decoder = get_aom_decoder_by_index(i);
clang-format's avatar
clang-format committed
188
    if (decoder->fourcc == fourcc) return decoder;
189 190
  }

191 192 193
  return NULL;
}

194 195
#endif  // CONFIG_DECODERS

Adrian Grange's avatar
Adrian Grange committed
196 197 198
// TODO(dkovalev): move this function to aom_image.{c, h}, so it will be part
// of aom_image_t support
int aom_img_plane_width(const aom_image_t *img, int plane) {
199 200 201 202 203 204
  if (plane > 0 && img->x_chroma_shift > 0)
    return (img->d_w + 1) >> img->x_chroma_shift;
  else
    return img->d_w;
}

Adrian Grange's avatar
Adrian Grange committed
205
int aom_img_plane_height(const aom_image_t *img, int plane) {
clang-format's avatar
clang-format committed
206
  if (plane > 0 && img->y_chroma_shift > 0)
207 208 209 210 211
    return (img->d_h + 1) >> img->y_chroma_shift;
  else
    return img->d_h;
}

Adrian Grange's avatar
Adrian Grange committed
212
void aom_img_write(const aom_image_t *img, FILE *file) {
213
  int plane;
214 215 216 217

  for (plane = 0; plane < 3; ++plane) {
    const unsigned char *buf = img->planes[plane];
    const int stride = img->stride[plane];
Adrian Grange's avatar
Adrian Grange committed
218
    const int w = aom_img_plane_width(img, plane) *
Adrian Grange's avatar
Adrian Grange committed
219
                  ((img->fmt & AOM_IMG_FMT_HIGHBITDEPTH) ? 2 : 1);
Adrian Grange's avatar
Adrian Grange committed
220
    const int h = aom_img_plane_height(img, plane);
221
    int y;
222

223 224 225 226 227 228
    for (y = 0; y < h; ++y) {
      fwrite(buf, 1, w, file);
      buf += stride;
    }
  }
}
229

Adrian Grange's avatar
Adrian Grange committed
230
int aom_img_read(aom_image_t *img, FILE *file) {
231 232 233 234 235
  int plane;

  for (plane = 0; plane < 3; ++plane) {
    unsigned char *buf = img->planes[plane];
    const int stride = img->stride[plane];
Adrian Grange's avatar
Adrian Grange committed
236
    const int w = aom_img_plane_width(img, plane) *
Adrian Grange's avatar
Adrian Grange committed
237
                  ((img->fmt & AOM_IMG_FMT_HIGHBITDEPTH) ? 2 : 1);
Adrian Grange's avatar
Adrian Grange committed
238
    const int h = aom_img_plane_height(img, plane);
239 240 241
    int y;

    for (y = 0; y < h; ++y) {
clang-format's avatar
clang-format committed
242
      if (fread(buf, 1, w, file) != (size_t)w) return 0;
243 244 245 246 247 248 249
      buf += stride;
    }
  }

  return 1;
}

250 251 252 253 254 255 256 257 258 259 260
// TODO(dkovalev) change sse_to_psnr signature: double -> int64_t
double sse_to_psnr(double samples, double peak, double sse) {
  static const double kMaxPSNR = 100.0;

  if (sse > 0.0) {
    const double psnr = 10.0 * log10(samples * peak * peak / sse);
    return psnr > kMaxPSNR ? kMaxPSNR : psnr;
  } else {
    return kMaxPSNR;
  }
}
261 262

// TODO(debargha): Consolidate the functions below into a separate file.
263
#if CONFIG_AOM_HIGHBITDEPTH
Adrian Grange's avatar
Adrian Grange committed
264
static void highbd_img_upshift(aom_image_t *dst, aom_image_t *src,
265 266 267 268
                               int input_shift) {
  // Note the offset is 1 less than half.
  const int offset = input_shift > 0 ? (1 << (input_shift - 1)) - 1 : 0;
  int plane;
269
  if (dst->d_w != src->d_w || dst->d_h != src->d_h ||
270
      dst->x_chroma_shift != src->x_chroma_shift ||
clang-format's avatar
clang-format committed
271 272
      dst->y_chroma_shift != src->y_chroma_shift || dst->fmt != src->fmt ||
      input_shift < 0) {
273 274 275
    fatal("Unsupported image conversion");
  }
  switch (src->fmt) {
Adrian Grange's avatar
Adrian Grange committed
276 277 278 279
    case AOM_IMG_FMT_I42016:
    case AOM_IMG_FMT_I42216:
    case AOM_IMG_FMT_I44416:
    case AOM_IMG_FMT_I44016: break;
clang-format's avatar
clang-format committed
280
    default: fatal("Unsupported image conversion"); break;
281 282
  }
  for (plane = 0; plane < 3; plane++) {
283 284
    int w = src->d_w;
    int h = src->d_h;
285 286
    int x, y;
    if (plane) {
287 288
      w = (w + src->x_chroma_shift) >> src->x_chroma_shift;
      h = (h + src->y_chroma_shift) >> src->y_chroma_shift;
289 290 291 292 293 294
    }
    for (y = 0; y < h; y++) {
      uint16_t *p_src =
          (uint16_t *)(src->planes[plane] + y * src->stride[plane]);
      uint16_t *p_dst =
          (uint16_t *)(dst->planes[plane] + y * dst->stride[plane]);
clang-format's avatar
clang-format committed
295
      for (x = 0; x < w; x++) *p_dst++ = (*p_src++ << input_shift) + offset;
296 297 298 299
    }
  }
}

Adrian Grange's avatar
Adrian Grange committed
300
static void lowbd_img_upshift(aom_image_t *dst, aom_image_t *src,
301 302 303 304
                              int input_shift) {
  // Note the offset is 1 less than half.
  const int offset = input_shift > 0 ? (1 << (input_shift - 1)) - 1 : 0;
  int plane;
305
  if (dst->d_w != src->d_w || dst->d_h != src->d_h ||
306 307
      dst->x_chroma_shift != src->x_chroma_shift ||
      dst->y_chroma_shift != src->y_chroma_shift ||
Adrian Grange's avatar
Adrian Grange committed
308
      dst->fmt != src->fmt + AOM_IMG_FMT_HIGHBITDEPTH || input_shift < 0) {
309 310 311
    fatal("Unsupported image conversion");
  }
  switch (src->fmt) {
Adrian Grange's avatar
Adrian Grange committed
312 313 314 315
    case AOM_IMG_FMT_I420:
    case AOM_IMG_FMT_I422:
    case AOM_IMG_FMT_I444:
    case AOM_IMG_FMT_I440: break;
clang-format's avatar
clang-format committed
316
    default: fatal("Unsupported image conversion"); break;
317 318
  }
  for (plane = 0; plane < 3; plane++) {
319 320
    int w = src->d_w;
    int h = src->d_h;
321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336
    int x, y;
    if (plane) {
      w = (w + src->x_chroma_shift) >> src->x_chroma_shift;
      h = (h + src->y_chroma_shift) >> src->y_chroma_shift;
    }
    for (y = 0; y < h; y++) {
      uint8_t *p_src = src->planes[plane] + y * src->stride[plane];
      uint16_t *p_dst =
          (uint16_t *)(dst->planes[plane] + y * dst->stride[plane]);
      for (x = 0; x < w; x++) {
        *p_dst++ = (*p_src++ << input_shift) + offset;
      }
    }
  }
}

Adrian Grange's avatar
Adrian Grange committed
337
void aom_img_upshift(aom_image_t *dst, aom_image_t *src, int input_shift) {
Adrian Grange's avatar
Adrian Grange committed
338
  if (src->fmt & AOM_IMG_FMT_HIGHBITDEPTH) {
339 340 341 342 343 344
    highbd_img_upshift(dst, src, input_shift);
  } else {
    lowbd_img_upshift(dst, src, input_shift);
  }
}

Adrian Grange's avatar
Adrian Grange committed
345
void aom_img_truncate_16_to_8(aom_image_t *dst, aom_image_t *src) {
346
  int plane;
Adrian Grange's avatar
Adrian Grange committed
347
  if (dst->fmt + AOM_IMG_FMT_HIGHBITDEPTH != src->fmt || dst->d_w != src->d_w ||
clang-format's avatar
clang-format committed
348
      dst->d_h != src->d_h || dst->x_chroma_shift != src->x_chroma_shift ||
349 350 351 352
      dst->y_chroma_shift != src->y_chroma_shift) {
    fatal("Unsupported image conversion");
  }
  switch (dst->fmt) {
Adrian Grange's avatar
Adrian Grange committed
353 354 355 356
    case AOM_IMG_FMT_I420:
    case AOM_IMG_FMT_I422:
    case AOM_IMG_FMT_I444:
    case AOM_IMG_FMT_I440: break;
clang-format's avatar
clang-format committed
357
    default: fatal("Unsupported image conversion"); break;
358 359 360 361 362 363
  }
  for (plane = 0; plane < 3; plane++) {
    int w = src->d_w;
    int h = src->d_h;
    int x, y;
    if (plane) {
364 365
      w = (w + src->x_chroma_shift) >> src->x_chroma_shift;
      h = (h + src->y_chroma_shift) >> src->y_chroma_shift;
366 367 368 369 370 371
    }
    for (y = 0; y < h; y++) {
      uint16_t *p_src =
          (uint16_t *)(src->planes[plane] + y * src->stride[plane]);
      uint8_t *p_dst = dst->planes[plane] + y * dst->stride[plane];
      for (x = 0; x < w; x++) {
Yaowu Xu's avatar
Yaowu Xu committed
372
        *p_dst++ = (uint8_t)(*p_src++);
373 374 375 376 377
      }
    }
  }
}

Adrian Grange's avatar
Adrian Grange committed
378
static void highbd_img_downshift(aom_image_t *dst, aom_image_t *src,
379 380 381 382
                                 int down_shift) {
  int plane;
  if (dst->d_w != src->d_w || dst->d_h != src->d_h ||
      dst->x_chroma_shift != src->x_chroma_shift ||
clang-format's avatar
clang-format committed
383 384
      dst->y_chroma_shift != src->y_chroma_shift || dst->fmt != src->fmt ||
      down_shift < 0) {
385 386 387
    fatal("Unsupported image conversion");
  }
  switch (src->fmt) {
Adrian Grange's avatar
Adrian Grange committed
388 389 390 391
    case AOM_IMG_FMT_I42016:
    case AOM_IMG_FMT_I42216:
    case AOM_IMG_FMT_I44416:
    case AOM_IMG_FMT_I44016: break;
clang-format's avatar
clang-format committed
392
    default: fatal("Unsupported image conversion"); break;
393 394 395 396 397 398 399 400 401 402 403 404 405 406
  }
  for (plane = 0; plane < 3; plane++) {
    int w = src->d_w;
    int h = src->d_h;
    int x, y;
    if (plane) {
      w = (w + src->x_chroma_shift) >> src->x_chroma_shift;
      h = (h + src->y_chroma_shift) >> src->y_chroma_shift;
    }
    for (y = 0; y < h; y++) {
      uint16_t *p_src =
          (uint16_t *)(src->planes[plane] + y * src->stride[plane]);
      uint16_t *p_dst =
          (uint16_t *)(dst->planes[plane] + y * dst->stride[plane]);
clang-format's avatar
clang-format committed
407
      for (x = 0; x < w; x++) *p_dst++ = *p_src++ >> down_shift;
408 409 410 411
    }
  }
}

Adrian Grange's avatar
Adrian Grange committed
412
static void lowbd_img_downshift(aom_image_t *dst, aom_image_t *src,
413 414 415 416 417
                                int down_shift) {
  int plane;
  if (dst->d_w != src->d_w || dst->d_h != src->d_h ||
      dst->x_chroma_shift != src->x_chroma_shift ||
      dst->y_chroma_shift != src->y_chroma_shift ||
Adrian Grange's avatar
Adrian Grange committed
418
      src->fmt != dst->fmt + AOM_IMG_FMT_HIGHBITDEPTH || down_shift < 0) {
419 420 421
    fatal("Unsupported image conversion");
  }
  switch (dst->fmt) {
Adrian Grange's avatar
Adrian Grange committed
422 423 424 425
    case AOM_IMG_FMT_I420:
    case AOM_IMG_FMT_I422:
    case AOM_IMG_FMT_I444:
    case AOM_IMG_FMT_I440: break;
clang-format's avatar
clang-format committed
426
    default: fatal("Unsupported image conversion"); break;
427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446
  }
  for (plane = 0; plane < 3; plane++) {
    int w = src->d_w;
    int h = src->d_h;
    int x, y;
    if (plane) {
      w = (w + src->x_chroma_shift) >> src->x_chroma_shift;
      h = (h + src->y_chroma_shift) >> src->y_chroma_shift;
    }
    for (y = 0; y < h; y++) {
      uint16_t *p_src =
          (uint16_t *)(src->planes[plane] + y * src->stride[plane]);
      uint8_t *p_dst = dst->planes[plane] + y * dst->stride[plane];
      for (x = 0; x < w; x++) {
        *p_dst++ = *p_src++ >> down_shift;
      }
    }
  }
}

Adrian Grange's avatar
Adrian Grange committed
447
void aom_img_downshift(aom_image_t *dst, aom_image_t *src, int down_shift) {
Adrian Grange's avatar
Adrian Grange committed
448
  if (dst->fmt & AOM_IMG_FMT_HIGHBITDEPTH) {
449 450 451 452 453
    highbd_img_downshift(dst, src, down_shift);
  } else {
    lowbd_img_downshift(dst, src, down_shift);
  }
}
454
#endif  // CONFIG_AOM_HIGHBITDEPTH