Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/third_party/aom/common/tools_common.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
3
 *
4
 * This source code is subject to the terms of the BSD 2 Clause License and
5
 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6
 * was not distributed with this source code in the LICENSE file, you can
7
 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8
 * Media Patent License 1.0 was not distributed with this source code in the
9
 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10
 */
11
12
#include "common/tools_common.h"
13
14
#include <math.h>
15
#include <stdarg.h>
16
#include <stdio.h>
17
#include <stdlib.h>
18
#include <string.h>
19
20
#if CONFIG_AV1_ENCODER
21
#include "aom/aomcx.h"
22
#endif
23
24
#if CONFIG_AV1_DECODER
25
#include "aom/aomdx.h"
26
#endif
27
28
#if defined(_WIN32) || defined(__OS2__)
29
#include <io.h>
30
#include <fcntl.h>
31
32
#ifdef __OS2__
33
#define _setmode setmode
34
#define _fileno fileno
35
#define _O_BINARY O_BINARY
36
#endif
37
#endif
38
39
#define LOG_ERROR(label)               \
40
0
  do {                                 \
41
0
    const char *l = label;             \
42
0
    va_list ap;                        \
43
0
    va_start(ap, fmt);                 \
44
0
    if (l) fprintf(stderr, "%s: ", l); \
45
0
    vfprintf(stderr, fmt, ap);         \
46
0
    fprintf(stderr, "\n");             \
47
0
    va_end(ap);                        \
48
0
  } while (0)
49
50
0
FILE *set_binary_mode(FILE *stream) {
51
0
  (void)stream;
52
#if defined(_WIN32) || defined(__OS2__)
53
  _setmode(_fileno(stream), _O_BINARY);
54
#endif
55
  return stream;
56
0
}
57
58
0
void die(const char *fmt, ...) {
59
0
  LOG_ERROR(NULL);
60
0
  usage_exit();
61
0
}
62
63
0
void fatal(const char *fmt, ...) {
64
0
  LOG_ERROR("Fatal");
65
0
  exit(EXIT_FAILURE);
66
0
}
67
68
0
void warn(const char *fmt, ...) { LOG_ERROR("Warning"); }
69
70
0
void die_codec(aom_codec_ctx_t *ctx, const char *s) {
71
0
  const char *detail = aom_codec_error_detail(ctx);
72
0
73
0
  printf("%s: %s\n", s, aom_codec_error(ctx));
74
0
  if (detail) printf("    %s\n", detail);
75
0
  exit(EXIT_FAILURE);
76
0
}
77
78
0
int read_yuv_frame(struct AvxInputContext *input_ctx, aom_image_t *yuv_frame) {
79
0
  FILE *f = input_ctx->file;
80
0
  struct FileTypeDetectionBuffer *detect = &input_ctx->detect;
81
0
  int plane = 0;
82
0
  int shortread = 0;
83
0
  const int bytespp = (yuv_frame->fmt & AOM_IMG_FMT_HIGHBITDEPTH) ? 2 : 1;
84
0
85
0
  for (plane = 0; plane < 3; ++plane) {
86
0
    uint8_t *ptr;
87
0
    const int w = aom_img_plane_width(yuv_frame, plane);
88
0
    const int h = aom_img_plane_height(yuv_frame, plane);
89
0
    int r;
90
0
91
0
    /* Determine the correct plane based on the image format. The for-loop
92
0
     * always counts in Y,U,V order, but this may not match the order of
93
0
     * the data on disk.
94
0
     */
95
0
    switch (plane) {
96
0
      case 1:
97
0
        ptr =
98
0
            yuv_frame->planes[yuv_frame->fmt == AOM_IMG_FMT_YV12 ? AOM_PLANE_V
99
0
                                                                 : AOM_PLANE_U];
100
0
        break;
101
0
      case 2:
102
0
        ptr =
103
0
            yuv_frame->planes[yuv_frame->fmt == AOM_IMG_FMT_YV12 ? AOM_PLANE_U
104
0
                                                                 : AOM_PLANE_V];
105
0
        break;
106
0
      default: ptr = yuv_frame->planes[plane];
107
0
    }
108
0
109
0
    for (r = 0; r < h; ++r) {
110
0
      size_t needed = w * bytespp;
111
0
      size_t buf_position = 0;
112
0
      const size_t left = detect->buf_read - detect->position;
113
0
      if (left > 0) {
114
0
        const size_t more = (left < needed) ? left : needed;
115
0
        memcpy(ptr, detect->buf + detect->position, more);
116
0
        buf_position = more;
117
0
        needed -= more;
118
0
        detect->position += more;
119
0
      }
120
0
      if (needed > 0) {
121
0
        shortread |= (fread(ptr + buf_position, 1, needed, f) < needed);
122
0
      }
123
0
124
0
      ptr += yuv_frame->stride[plane];
125
0
    }
126
0
  }
127
0
128
0
  return shortread;
129
0
}
130
131
#if CONFIG_AV1_ENCODER
132
static const AvxInterface aom_encoders[] = {
133
  { "av1", AV1_FOURCC, &aom_codec_av1_cx },
134
};
135
136
int get_aom_encoder_count(void) {
137
  return sizeof(aom_encoders) / sizeof(aom_encoders[0]);
138
}
139
140
const AvxInterface *get_aom_encoder_by_index(int i) { return &aom_encoders[i]; }
141
142
const AvxInterface *get_aom_encoder_by_name(const char *name) {
143
  int i;
144
145
  for (i = 0; i < get_aom_encoder_count(); ++i) {
146
    const AvxInterface *encoder = get_aom_encoder_by_index(i);
147
    if (strcmp(encoder->name, name) == 0) return encoder;
148
  }
149
150
  return NULL;
151
}
152
#endif  // CONFIG_AV1_ENCODER
153
154
#if CONFIG_AV1_DECODER
155
static const AvxInterface aom_decoders[] = {
156
  { "av1", AV1_FOURCC, &aom_codec_av1_dx },
157
};
158
159
0
int get_aom_decoder_count(void) {
160
0
  return sizeof(aom_decoders) / sizeof(aom_decoders[0]);
161
0
}
162
163
0
const AvxInterface *get_aom_decoder_by_index(int i) { return &aom_decoders[i]; }
164
165
0
const AvxInterface *get_aom_decoder_by_name(const char *name) {
166
0
  int i;
167
0
168
0
  for (i = 0; i < get_aom_decoder_count(); ++i) {
169
0
    const AvxInterface *const decoder = get_aom_decoder_by_index(i);
170
0
    if (strcmp(decoder->name, name) == 0) return decoder;
171
0
  }
172
0
173
0
  return NULL;
174
0
}
175
176
0
const AvxInterface *get_aom_decoder_by_fourcc(uint32_t fourcc) {
177
0
  int i;
178
0
179
0
  for (i = 0; i < get_aom_decoder_count(); ++i) {
180
0
    const AvxInterface *const decoder = get_aom_decoder_by_index(i);
181
0
    if (decoder->fourcc == fourcc) return decoder;
182
0
  }
183
0
184
0
  return NULL;
185
0
}
186
#endif  // CONFIG_AV1_DECODER
187
188
0
void aom_img_write(const aom_image_t *img, FILE *file) {
189
0
  int plane;
190
0
191
0
  for (plane = 0; plane < 3; ++plane) {
192
0
    const unsigned char *buf = img->planes[plane];
193
0
    const int stride = img->stride[plane];
194
0
    const int w = aom_img_plane_width(img, plane) *
195
0
                  ((img->fmt & AOM_IMG_FMT_HIGHBITDEPTH) ? 2 : 1);
196
0
    const int h = aom_img_plane_height(img, plane);
197
0
    int y;
198
0
199
0
    for (y = 0; y < h; ++y) {
200
0
      fwrite(buf, 1, w, file);
201
0
      buf += stride;
202
0
    }
203
0
  }
204
0
}
205
206
0
int aom_img_read(aom_image_t *img, FILE *file) {
207
0
  int plane;
208
0
209
0
  for (plane = 0; plane < 3; ++plane) {
210
0
    unsigned char *buf = img->planes[plane];
211
0
    const int stride = img->stride[plane];
212
0
    const int w = aom_img_plane_width(img, plane) *
213
0
                  ((img->fmt & AOM_IMG_FMT_HIGHBITDEPTH) ? 2 : 1);
214
0
    const int h = aom_img_plane_height(img, plane);
215
0
    int y;
216
0
217
0
    for (y = 0; y < h; ++y) {
218
0
      if (fread(buf, 1, w, file) != (size_t)w) return 0;
219
0
      buf += stride;
220
0
    }
221
0
  }
222
0
223
0
  return 1;
224
0
}
225
226
// TODO(dkovalev) change sse_to_psnr signature: double -> int64_t
227
0
double sse_to_psnr(double samples, double peak, double sse) {
228
0
  static const double kMaxPSNR = 100.0;
229
0
230
0
  if (sse > 0.0) {
231
0
    const double psnr = 10.0 * log10(samples * peak * peak / sse);
232
0
    return psnr > kMaxPSNR ? kMaxPSNR : psnr;
233
0
  } else {
234
0
    return kMaxPSNR;
235
0
  }
236
0
}
237
238
// TODO(debargha): Consolidate the functions below into a separate file.
239
static void highbd_img_upshift(aom_image_t *dst, const aom_image_t *src,
240
0
                               int input_shift) {
241
0
  // Note the offset is 1 less than half.
242
0
  const int offset = input_shift > 0 ? (1 << (input_shift - 1)) - 1 : 0;
243
0
  int plane;
244
0
  if (dst->d_w != src->d_w || dst->d_h != src->d_h ||
245
0
      dst->x_chroma_shift != src->x_chroma_shift ||
246
0
      dst->y_chroma_shift != src->y_chroma_shift || dst->fmt != src->fmt ||
247
0
      input_shift < 0) {
248
0
    fatal("Unsupported image conversion");
249
0
  }
250
0
  switch (src->fmt) {
251
0
    case AOM_IMG_FMT_I42016:
252
0
    case AOM_IMG_FMT_I42216:
253
0
    case AOM_IMG_FMT_I44416: break;
254
0
    default: fatal("Unsupported image conversion"); break;
255
0
  }
256
0
  for (plane = 0; plane < 3; plane++) {
257
0
    int w = src->d_w;
258
0
    int h = src->d_h;
259
0
    int x, y;
260
0
    if (plane) {
261
0
      w = (w + src->x_chroma_shift) >> src->x_chroma_shift;
262
0
      h = (h + src->y_chroma_shift) >> src->y_chroma_shift;
263
0
    }
264
0
    for (y = 0; y < h; y++) {
265
0
      const uint16_t *p_src =
266
0
          (const uint16_t *)(src->planes[plane] + y * src->stride[plane]);
267
0
      uint16_t *p_dst =
268
0
          (uint16_t *)(dst->planes[plane] + y * dst->stride[plane]);
269
0
      for (x = 0; x < w; x++) *p_dst++ = (*p_src++ << input_shift) + offset;
270
0
    }
271
0
  }
272
0
}
273
274
static void lowbd_img_upshift(aom_image_t *dst, const aom_image_t *src,
275
0
                              int input_shift) {
276
0
  // Note the offset is 1 less than half.
277
0
  const int offset = input_shift > 0 ? (1 << (input_shift - 1)) - 1 : 0;
278
0
  int plane;
279
0
  if (dst->d_w != src->d_w || dst->d_h != src->d_h ||
280
0
      dst->x_chroma_shift != src->x_chroma_shift ||
281
0
      dst->y_chroma_shift != src->y_chroma_shift ||
282
0
      dst->fmt != src->fmt + AOM_IMG_FMT_HIGHBITDEPTH || input_shift < 0) {
283
0
    fatal("Unsupported image conversion");
284
0
  }
285
0
  switch (src->fmt) {
286
0
    case AOM_IMG_FMT_I420:
287
0
    case AOM_IMG_FMT_I422:
288
0
    case AOM_IMG_FMT_I444: break;
289
0
    default: fatal("Unsupported image conversion"); break;
290
0
  }
291
0
  for (plane = 0; plane < 3; plane++) {
292
0
    int w = src->d_w;
293
0
    int h = src->d_h;
294
0
    int x, y;
295
0
    if (plane) {
296
0
      w = (w + src->x_chroma_shift) >> src->x_chroma_shift;
297
0
      h = (h + src->y_chroma_shift) >> src->y_chroma_shift;
298
0
    }
299
0
    for (y = 0; y < h; y++) {
300
0
      const uint8_t *p_src = src->planes[plane] + y * src->stride[plane];
301
0
      uint16_t *p_dst =
302
0
          (uint16_t *)(dst->planes[plane] + y * dst->stride[plane]);
303
0
      for (x = 0; x < w; x++) {
304
0
        *p_dst++ = (*p_src++ << input_shift) + offset;
305
0
      }
306
0
    }
307
0
  }
308
0
}
309
310
void aom_img_upshift(aom_image_t *dst, const aom_image_t *src,
311
0
                     int input_shift) {
312
0
  if (src->fmt & AOM_IMG_FMT_HIGHBITDEPTH) {
313
0
    highbd_img_upshift(dst, src, input_shift);
314
0
  } else {
315
0
    lowbd_img_upshift(dst, src, input_shift);
316
0
  }
317
0
}
318
319
0
void aom_img_truncate_16_to_8(aom_image_t *dst, const aom_image_t *src) {
320
0
  int plane;
321
0
  if (dst->fmt + AOM_IMG_FMT_HIGHBITDEPTH != src->fmt || dst->d_w != src->d_w ||
322
0
      dst->d_h != src->d_h || dst->x_chroma_shift != src->x_chroma_shift ||
323
0
      dst->y_chroma_shift != src->y_chroma_shift) {
324
0
    fatal("Unsupported image conversion");
325
0
  }
326
0
  switch (dst->fmt) {
327
0
    case AOM_IMG_FMT_I420:
328
0
    case AOM_IMG_FMT_I422:
329
0
    case AOM_IMG_FMT_I444: break;
330
0
    default: fatal("Unsupported image conversion"); break;
331
0
  }
332
0
  for (plane = 0; plane < 3; plane++) {
333
0
    int w = src->d_w;
334
0
    int h = src->d_h;
335
0
    int x, y;
336
0
    if (plane) {
337
0
      w = (w + src->x_chroma_shift) >> src->x_chroma_shift;
338
0
      h = (h + src->y_chroma_shift) >> src->y_chroma_shift;
339
0
    }
340
0
    for (y = 0; y < h; y++) {
341
0
      const uint16_t *p_src =
342
0
          (const uint16_t *)(src->planes[plane] + y * src->stride[plane]);
343
0
      uint8_t *p_dst = dst->planes[plane] + y * dst->stride[plane];
344
0
      for (x = 0; x < w; x++) {
345
0
        *p_dst++ = (uint8_t)(*p_src++);
346
0
      }
347
0
    }
348
0
  }
349
0
}
350
351
static void highbd_img_downshift(aom_image_t *dst, const aom_image_t *src,
352
0
                                 int down_shift) {
353
0
  int plane;
354
0
  if (dst->d_w != src->d_w || dst->d_h != src->d_h ||
355
0
      dst->x_chroma_shift != src->x_chroma_shift ||
356
0
      dst->y_chroma_shift != src->y_chroma_shift || dst->fmt != src->fmt ||
357
0
      down_shift < 0) {
358
0
    fatal("Unsupported image conversion");
359
0
  }
360
0
  switch (src->fmt) {
361
0
    case AOM_IMG_FMT_I42016:
362
0
    case AOM_IMG_FMT_I42216:
363
0
    case AOM_IMG_FMT_I44416: break;
364
0
    default: fatal("Unsupported image conversion"); break;
365
0
  }
366
0
  for (plane = 0; plane < 3; plane++) {
367
0
    int w = src->d_w;
368
0
    int h = src->d_h;
369
0
    int x, y;
370
0
    if (plane) {
371
0
      w = (w + src->x_chroma_shift) >> src->x_chroma_shift;
372
0
      h = (h + src->y_chroma_shift) >> src->y_chroma_shift;
373
0
    }
374
0
    for (y = 0; y < h; y++) {
375
0
      const uint16_t *p_src =
376
0
          (const uint16_t *)(src->planes[plane] + y * src->stride[plane]);
377
0
      uint16_t *p_dst =
378
0
          (uint16_t *)(dst->planes[plane] + y * dst->stride[plane]);
379
0
      for (x = 0; x < w; x++) *p_dst++ = *p_src++ >> down_shift;
380
0
    }
381
0
  }
382
0
}
383
384
static void lowbd_img_downshift(aom_image_t *dst, const aom_image_t *src,
385
0
                                int down_shift) {
386
0
  int plane;
387
0
  if (dst->d_w != src->d_w || dst->d_h != src->d_h ||
388
0
      dst->x_chroma_shift != src->x_chroma_shift ||
389
0
      dst->y_chroma_shift != src->y_chroma_shift ||
390
0
      src->fmt != dst->fmt + AOM_IMG_FMT_HIGHBITDEPTH || down_shift < 0) {
391
0
    fatal("Unsupported image conversion");
392
0
  }
393
0
  switch (dst->fmt) {
394
0
    case AOM_IMG_FMT_I420:
395
0
    case AOM_IMG_FMT_I422:
396
0
    case AOM_IMG_FMT_I444: break;
397
0
    default: fatal("Unsupported image conversion"); break;
398
0
  }
399
0
  for (plane = 0; plane < 3; plane++) {
400
0
    int w = src->d_w;
401
0
    int h = src->d_h;
402
0
    int x, y;
403
0
    if (plane) {
404
0
      w = (w + src->x_chroma_shift) >> src->x_chroma_shift;
405
0
      h = (h + src->y_chroma_shift) >> src->y_chroma_shift;
406
0
    }
407
0
    for (y = 0; y < h; y++) {
408
0
      const uint16_t *p_src =
409
0
          (const uint16_t *)(src->planes[plane] + y * src->stride[plane]);
410
0
      uint8_t *p_dst = dst->planes[plane] + y * dst->stride[plane];
411
0
      for (x = 0; x < w; x++) {
412
0
        *p_dst++ = *p_src++ >> down_shift;
413
0
      }
414
0
    }
415
0
  }
416
0
}
417
418
void aom_img_downshift(aom_image_t *dst, const aom_image_t *src,
419
0
                       int down_shift) {
420
0
  if (dst->fmt & AOM_IMG_FMT_HIGHBITDEPTH) {
421
0
    highbd_img_downshift(dst, src, down_shift);
422
0
  } else {
423
0
    lowbd_img_downshift(dst, src, down_shift);
424
0
  }
425
0
}