Files
vpx/tools_common.c
Yaowu Xu f883b42cab Port renaming changes from AOMedia
Cherry-Picked the following commits:
0defd8f Changed "WebM" to "AOMedia" & "webm" to "aomedia"
54e6676 Replace "VPx" by "AVx"
5082a36 Change "Vpx" to "Avx"
7df44f1 Replace "Vp9" w/ "Av1"
967f722 Remove kVp9CodecId
828f30c Change "Vp8" to "AOM"
030b5ff AUTHORS regenerated
2524cae Add ref-mv experimental flag
016762b Change copyright notice to AOMedia form
81e5526 Replace vp9 w/ av1
9b94565 Add missing files
fa8ca9f Change "vp9" to "av1"
ec838b7  Convert "vp8" to "aom"
80edfa0 Change "VP9" to "AV1"
d1a11fb Change "vp8" to "aom"
7b58251 Point to WebM test data
dd1a5c8 Replace "VP8" with "AOM"
ff00fc0 Change "VPX" to "AOM"
01dee0b Change "vp10" to "av1" in source code
cebe6f0 Convert "vpx" to "aom"
17b0567 rename vp10*.mk to av1_*.mk
fe5f8a8 rename files vp10_* to av1_*

Change-Id: I6fc3d18eb11fc171e46140c836ad5339cf6c9419
2016-08-31 18:19:03 -07:00

455 lines
13 KiB
C

/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <math.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "./tools_common.h"
#if CONFIG_AV1_ENCODER
#include "aom/aomcx.h"
#endif
#if CONFIG_AV1_DECODER
#include "aom/aomdx.h"
#endif
#if defined(_WIN32) || defined(__OS2__)
#include <io.h>
#include <fcntl.h>
#ifdef __OS2__
#define _setmode setmode
#define _fileno fileno
#define _O_BINARY O_BINARY
#endif
#endif
#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)
FILE *set_binary_mode(FILE *stream) {
(void)stream;
#if defined(_WIN32) || defined(__OS2__)
_setmode(_fileno(stream), _O_BINARY);
#endif
return stream;
}
void die(const char *fmt, ...) {
LOG_ERROR(NULL);
usage_exit();
}
void fatal(const char *fmt, ...) {
LOG_ERROR("Fatal");
exit(EXIT_FAILURE);
}
void warn(const char *fmt, ...) { LOG_ERROR("Warning"); }
void die_codec(aom_codec_ctx_t *ctx, const char *s) {
const char *detail = aom_codec_error_detail(ctx);
printf("%s: %s\n", s, aom_codec_error(ctx));
if (detail) printf(" %s\n", detail);
exit(EXIT_FAILURE);
}
int read_yuv_frame(struct AvxInputContext *input_ctx, aom_image_t *yuv_frame) {
FILE *f = input_ctx->file;
struct FileTypeDetectionBuffer *detect = &input_ctx->detect;
int plane = 0;
int shortread = 0;
const int bytespp = (yuv_frame->fmt & AOM_IMG_FMT_HIGHBITDEPTH) ? 2 : 1;
for (plane = 0; plane < 3; ++plane) {
uint8_t *ptr;
const int w = aom_img_plane_width(yuv_frame, plane);
const int h = aom_img_plane_height(yuv_frame, plane);
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:
ptr =
yuv_frame->planes[yuv_frame->fmt == AOM_IMG_FMT_YV12 ? AOM_PLANE_V
: AOM_PLANE_U];
break;
case 2:
ptr =
yuv_frame->planes[yuv_frame->fmt == AOM_IMG_FMT_YV12 ? AOM_PLANE_U
: AOM_PLANE_V];
break;
default: ptr = yuv_frame->planes[plane];
}
for (r = 0; r < h; ++r) {
size_t needed = w * bytespp;
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;
}
#if CONFIG_ENCODERS
static const AvxInterface aom_encoders[] = {
#if CONFIG_AV1_ENCODER
{ "av1", AV1_FOURCC, &aom_codec_av1_cx },
#endif
};
int get_aom_encoder_count(void) {
return sizeof(aom_encoders) / sizeof(aom_encoders[0]);
}
const AvxInterface *get_aom_encoder_by_index(int i) { return &aom_encoders[i]; }
const AvxInterface *get_aom_encoder_by_name(const char *name) {
int i;
for (i = 0; i < get_aom_encoder_count(); ++i) {
const AvxInterface *encoder = get_aom_encoder_by_index(i);
if (strcmp(encoder->name, name) == 0) return encoder;
}
return NULL;
}
#endif // CONFIG_ENCODERS
#if CONFIG_DECODERS
static const AvxInterface aom_decoders[] = {
#if CONFIG_AV1_DECODER
{ "av1", AV1_FOURCC, &aom_codec_av1_dx },
#endif
};
int get_aom_decoder_count(void) {
return sizeof(aom_decoders) / sizeof(aom_decoders[0]);
}
const AvxInterface *get_aom_decoder_by_index(int i) { return &aom_decoders[i]; }
const AvxInterface *get_aom_decoder_by_name(const char *name) {
int i;
for (i = 0; i < get_aom_decoder_count(); ++i) {
const AvxInterface *const decoder = get_aom_decoder_by_index(i);
if (strcmp(decoder->name, name) == 0) return decoder;
}
return NULL;
}
const AvxInterface *get_aom_decoder_by_fourcc(uint32_t fourcc) {
int i;
for (i = 0; i < get_aom_decoder_count(); ++i) {
const AvxInterface *const decoder = get_aom_decoder_by_index(i);
if (decoder->fourcc == fourcc) return decoder;
}
return NULL;
}
#endif // CONFIG_DECODERS
// 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) {
if (plane > 0 && img->x_chroma_shift > 0)
return (img->d_w + 1) >> img->x_chroma_shift;
else
return img->d_w;
}
int aom_img_plane_height(const aom_image_t *img, int plane) {
if (plane > 0 && img->y_chroma_shift > 0)
return (img->d_h + 1) >> img->y_chroma_shift;
else
return img->d_h;
}
void aom_img_write(const aom_image_t *img, FILE *file) {
int plane;
for (plane = 0; plane < 3; ++plane) {
const unsigned char *buf = img->planes[plane];
const int stride = img->stride[plane];
const int w = aom_img_plane_width(img, plane) *
((img->fmt & AOM_IMG_FMT_HIGHBITDEPTH) ? 2 : 1);
const int h = aom_img_plane_height(img, plane);
int y;
for (y = 0; y < h; ++y) {
fwrite(buf, 1, w, file);
buf += stride;
}
}
}
int aom_img_read(aom_image_t *img, FILE *file) {
int plane;
for (plane = 0; plane < 3; ++plane) {
unsigned char *buf = img->planes[plane];
const int stride = img->stride[plane];
const int w = aom_img_plane_width(img, plane) *
((img->fmt & AOM_IMG_FMT_HIGHBITDEPTH) ? 2 : 1);
const int h = aom_img_plane_height(img, plane);
int y;
for (y = 0; y < h; ++y) {
if (fread(buf, 1, w, file) != (size_t)w) return 0;
buf += stride;
}
}
return 1;
}
// 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;
}
}
// TODO(debargha): Consolidate the functions below into a separate file.
#if CONFIG_AOM_HIGHBITDEPTH
static void highbd_img_upshift(aom_image_t *dst, aom_image_t *src,
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;
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 || dst->fmt != src->fmt ||
input_shift < 0) {
fatal("Unsupported image conversion");
}
switch (src->fmt) {
case AOM_IMG_FMT_I42016:
case AOM_IMG_FMT_I42216:
case AOM_IMG_FMT_I44416:
case AOM_IMG_FMT_I44016: break;
default: fatal("Unsupported image conversion"); break;
}
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]);
for (x = 0; x < w; x++) *p_dst++ = (*p_src++ << input_shift) + offset;
}
}
}
static void lowbd_img_upshift(aom_image_t *dst, aom_image_t *src,
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;
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 ||
dst->fmt != src->fmt + AOM_IMG_FMT_HIGHBITDEPTH || input_shift < 0) {
fatal("Unsupported image conversion");
}
switch (src->fmt) {
case AOM_IMG_FMT_I420:
case AOM_IMG_FMT_I422:
case AOM_IMG_FMT_I444:
case AOM_IMG_FMT_I440: break;
default: fatal("Unsupported image conversion"); break;
}
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++) {
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;
}
}
}
}
void aom_img_upshift(aom_image_t *dst, aom_image_t *src, int input_shift) {
if (src->fmt & AOM_IMG_FMT_HIGHBITDEPTH) {
highbd_img_upshift(dst, src, input_shift);
} else {
lowbd_img_upshift(dst, src, input_shift);
}
}
void aom_img_truncate_16_to_8(aom_image_t *dst, aom_image_t *src) {
int plane;
if (dst->fmt + AOM_IMG_FMT_HIGHBITDEPTH != src->fmt || 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) {
fatal("Unsupported image conversion");
}
switch (dst->fmt) {
case AOM_IMG_FMT_I420:
case AOM_IMG_FMT_I422:
case AOM_IMG_FMT_I444:
case AOM_IMG_FMT_I440: break;
default: fatal("Unsupported image conversion"); break;
}
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++ = (uint8_t)(*p_src++);
}
}
}
}
static void highbd_img_downshift(aom_image_t *dst, aom_image_t *src,
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 || dst->fmt != src->fmt ||
down_shift < 0) {
fatal("Unsupported image conversion");
}
switch (src->fmt) {
case AOM_IMG_FMT_I42016:
case AOM_IMG_FMT_I42216:
case AOM_IMG_FMT_I44416:
case AOM_IMG_FMT_I44016: break;
default: fatal("Unsupported image conversion"); break;
}
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]);
for (x = 0; x < w; x++) *p_dst++ = *p_src++ >> down_shift;
}
}
}
static void lowbd_img_downshift(aom_image_t *dst, aom_image_t *src,
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 ||
src->fmt != dst->fmt + AOM_IMG_FMT_HIGHBITDEPTH || down_shift < 0) {
fatal("Unsupported image conversion");
}
switch (dst->fmt) {
case AOM_IMG_FMT_I420:
case AOM_IMG_FMT_I422:
case AOM_IMG_FMT_I444:
case AOM_IMG_FMT_I440: break;
default: fatal("Unsupported image conversion"); break;
}
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;
}
}
}
}
void aom_img_downshift(aom_image_t *dst, aom_image_t *src, int down_shift) {
if (dst->fmt & AOM_IMG_FMT_HIGHBITDEPTH) {
highbd_img_downshift(dst, src, down_shift);
} else {
lowbd_img_downshift(dst, src, down_shift);
}
}
#endif // CONFIG_AOM_HIGHBITDEPTH