top-level: apply clang-format

Change-Id: Ibd5395bf8956a80f7c0df4d539c7a42c927a1fc7
This commit is contained in:
clang-format 2016-07-18 19:44:59 -07:00 committed by James Zern
parent 6e336f6e5f
commit 033dab9ca0
25 changed files with 1316 additions and 1442 deletions

88
args.c
View File

@ -8,7 +8,6 @@
* be found in the AUTHORS file in the root of the source tree. * be found in the AUTHORS file in the root of the source tree.
*/ */
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <limits.h> #include <limits.h>
@ -22,7 +21,6 @@ extern void die(const char *fmt, ...) __attribute__((noreturn));
extern void die(const char *fmt, ...); extern void die(const char *fmt, ...);
#endif #endif
struct arg arg_init(char **argv) { struct arg arg_init(char **argv) {
struct arg a; struct arg a;
@ -37,27 +35,22 @@ struct arg arg_init(char **argv) {
int arg_match(struct arg *arg_, const struct arg_def *def, char **argv) { int arg_match(struct arg *arg_, const struct arg_def *def, char **argv) {
struct arg arg; struct arg arg;
if (!argv[0] || argv[0][0] != '-') if (!argv[0] || argv[0][0] != '-') return 0;
return 0;
arg = arg_init(argv); arg = arg_init(argv);
if (def->short_name if (def->short_name && strlen(arg.argv[0]) == strlen(def->short_name) + 1 &&
&& strlen(arg.argv[0]) == strlen(def->short_name) + 1 !strcmp(arg.argv[0] + 1, def->short_name)) {
&& !strcmp(arg.argv[0] + 1, def->short_name)) {
arg.name = arg.argv[0] + 1; arg.name = arg.argv[0] + 1;
arg.val = def->has_val ? arg.argv[1] : NULL; arg.val = def->has_val ? arg.argv[1] : NULL;
arg.argv_step = def->has_val ? 2 : 1; arg.argv_step = def->has_val ? 2 : 1;
} else if (def->long_name) { } else if (def->long_name) {
const size_t name_len = strlen(def->long_name); const size_t name_len = strlen(def->long_name);
if (strlen(arg.argv[0]) >= name_len + 2 if (strlen(arg.argv[0]) >= name_len + 2 && arg.argv[0][1] == '-' &&
&& arg.argv[0][1] == '-' !strncmp(arg.argv[0] + 2, def->long_name, name_len) &&
&& !strncmp(arg.argv[0] + 2, def->long_name, name_len) (arg.argv[0][name_len + 2] == '=' ||
&& (arg.argv[0][name_len + 2] == '=' arg.argv[0][name_len + 2] == '\0')) {
|| arg.argv[0][name_len + 2] == '\0')) {
arg.name = arg.argv[0] + 2; arg.name = arg.argv[0] + 2;
arg.val = arg.name[name_len] == '=' ? arg.name + name_len + 1 : NULL; arg.val = arg.name[name_len] == '=' ? arg.name + name_len + 1 : NULL;
arg.argv_step = 1; arg.argv_step = 1;
@ -70,8 +63,7 @@ int arg_match(struct arg *arg_, const struct arg_def *def, char **argv) {
if (arg.name && arg.val && !def->has_val) if (arg.name && arg.val && !def->has_val)
die("Error: option %s requires no argument.\n", arg.name); die("Error: option %s requires no argument.\n", arg.name);
if (arg.name if (arg.name && (arg.val || !def->has_val)) {
&& (arg.val || !def->has_val)) {
arg.def = def; arg.def = def;
*arg_ = arg; *arg_ = arg;
return 1; return 1;
@ -80,15 +72,12 @@ int arg_match(struct arg *arg_, const struct arg_def *def, char **argv) {
return 0; return 0;
} }
const char *arg_next(struct arg *arg) { const char *arg_next(struct arg *arg) {
if (arg->argv[0]) if (arg->argv[0]) arg->argv += arg->argv_step;
arg->argv += arg->argv_step;
return *arg->argv; return *arg->argv;
} }
char **argv_dup(int argc, const char **argv) { char **argv_dup(int argc, const char **argv) {
char **new_argv = malloc((argc + 1) * sizeof(*argv)); char **new_argv = malloc((argc + 1) * sizeof(*argv));
@ -97,7 +86,6 @@ char **argv_dup(int argc, const char **argv) {
return new_argv; return new_argv;
} }
void arg_show_usage(FILE *fp, const struct arg_def *const *defs) { void arg_show_usage(FILE *fp, const struct arg_def *const *defs) {
char option_text[40] = { 0 }; char option_text[40] = { 0 };
@ -109,15 +97,12 @@ void arg_show_usage(FILE *fp, const struct arg_def *const *defs) {
if (def->short_name && def->long_name) { if (def->short_name && def->long_name) {
char *comma = def->has_val ? "," : ", "; char *comma = def->has_val ? "," : ", ";
snprintf(option_text, 37, "-%s%s%s --%s%6s", snprintf(option_text, 37, "-%s%s%s --%s%6s", def->short_name, short_val,
def->short_name, short_val, comma, comma, def->long_name, long_val);
def->long_name, long_val);
} else if (def->short_name) } else if (def->short_name)
snprintf(option_text, 37, "-%s%s", snprintf(option_text, 37, "-%s%s", def->short_name, short_val);
def->short_name, short_val);
else if (def->long_name) else if (def->long_name)
snprintf(option_text, 37, " --%s%s", snprintf(option_text, 37, " --%s%s", def->long_name, long_val);
def->long_name, long_val);
fprintf(fp, " %-37s\t%s\n", option_text, def->desc); fprintf(fp, " %-37s\t%s\n", option_text, def->desc);
@ -127,13 +112,11 @@ void arg_show_usage(FILE *fp, const struct arg_def *const *defs) {
fprintf(fp, " %-37s\t ", ""); fprintf(fp, " %-37s\t ", "");
for (listptr = def->enums; listptr->name; listptr++) for (listptr = def->enums; listptr->name; listptr++)
fprintf(fp, "%s%s", listptr->name, fprintf(fp, "%s%s", listptr->name, listptr[1].name ? ", " : "\n");
listptr[1].name ? ", " : "\n");
} }
} }
} }
unsigned int arg_parse_uint(const struct arg *arg) { unsigned int arg_parse_uint(const struct arg *arg) {
long int rawval; long int rawval;
char *endptr; char *endptr;
@ -141,18 +124,16 @@ unsigned int arg_parse_uint(const struct arg *arg) {
rawval = strtol(arg->val, &endptr, 10); rawval = strtol(arg->val, &endptr, 10);
if (arg->val[0] != '\0' && endptr[0] == '\0') { if (arg->val[0] != '\0' && endptr[0] == '\0') {
if (rawval >= 0 && rawval <= UINT_MAX) if (rawval >= 0 && rawval <= UINT_MAX) return rawval;
return rawval;
die("Option %s: Value %ld out of range for unsigned int\n", die("Option %s: Value %ld out of range for unsigned int\n", arg->name,
arg->name, rawval); rawval);
} }
die("Option %s: Invalid character '%c'\n", arg->name, *endptr); die("Option %s: Invalid character '%c'\n", arg->name, *endptr);
return 0; return 0;
} }
int arg_parse_int(const struct arg *arg) { int arg_parse_int(const struct arg *arg) {
long int rawval; long int rawval;
char *endptr; char *endptr;
@ -160,18 +141,16 @@ int arg_parse_int(const struct arg *arg) {
rawval = strtol(arg->val, &endptr, 10); rawval = strtol(arg->val, &endptr, 10);
if (arg->val[0] != '\0' && endptr[0] == '\0') { if (arg->val[0] != '\0' && endptr[0] == '\0') {
if (rawval >= INT_MIN && rawval <= INT_MAX) if (rawval >= INT_MIN && rawval <= INT_MAX) return rawval;
return rawval;
die("Option %s: Value %ld out of range for signed int\n", die("Option %s: Value %ld out of range for signed int\n", arg->name,
arg->name, rawval); rawval);
} }
die("Option %s: Invalid character '%c'\n", arg->name, *endptr); die("Option %s: Invalid character '%c'\n", arg->name, *endptr);
return 0; return 0;
} }
struct vpx_rational { struct vpx_rational {
int num; /**< fraction numerator */ int num; /**< fraction numerator */
int den; /**< fraction denominator */ int den; /**< fraction denominator */
@ -187,9 +166,11 @@ struct vpx_rational arg_parse_rational(const struct arg *arg) {
if (arg->val[0] != '\0' && endptr[0] == '/') { if (arg->val[0] != '\0' && endptr[0] == '/') {
if (rawval >= INT_MIN && rawval <= INT_MAX) if (rawval >= INT_MIN && rawval <= INT_MAX)
rat.num = rawval; rat.num = rawval;
else die("Option %s: Value %ld out of range for signed int\n", else
arg->name, rawval); die("Option %s: Value %ld out of range for signed int\n", arg->name,
} else die("Option %s: Expected / at '%c'\n", arg->name, *endptr); rawval);
} else
die("Option %s: Expected / at '%c'\n", arg->name, *endptr);
/* parse denominator */ /* parse denominator */
rawval = strtol(endptr + 1, &endptr, 10); rawval = strtol(endptr + 1, &endptr, 10);
@ -197,14 +178,15 @@ struct vpx_rational arg_parse_rational(const struct arg *arg) {
if (arg->val[0] != '\0' && endptr[0] == '\0') { if (arg->val[0] != '\0' && endptr[0] == '\0') {
if (rawval >= INT_MIN && rawval <= INT_MAX) if (rawval >= INT_MIN && rawval <= INT_MAX)
rat.den = rawval; rat.den = rawval;
else die("Option %s: Value %ld out of range for signed int\n", else
arg->name, rawval); die("Option %s: Value %ld out of range for signed int\n", arg->name,
} else die("Option %s: Invalid character '%c'\n", arg->name, *endptr); rawval);
} else
die("Option %s: Invalid character '%c'\n", arg->name, *endptr);
return rat; return rat;
} }
int arg_parse_enum(const struct arg *arg) { int arg_parse_enum(const struct arg *arg) {
const struct arg_enum_list *listptr; const struct arg_enum_list *listptr;
long int rawval; long int rawval;
@ -215,22 +197,18 @@ int arg_parse_enum(const struct arg *arg) {
if (arg->val[0] != '\0' && endptr[0] == '\0') { if (arg->val[0] != '\0' && endptr[0] == '\0') {
/* Got a raw value, make sure it's valid */ /* Got a raw value, make sure it's valid */
for (listptr = arg->def->enums; listptr->name; listptr++) for (listptr = arg->def->enums; listptr->name; listptr++)
if (listptr->val == rawval) if (listptr->val == rawval) return rawval;
return rawval;
} }
/* Next see if it can be parsed as a string */ /* Next see if it can be parsed as a string */
for (listptr = arg->def->enums; listptr->name; listptr++) for (listptr = arg->def->enums; listptr->name; listptr++)
if (!strcmp(arg->val, listptr->name)) if (!strcmp(arg->val, listptr->name)) return listptr->val;
return listptr->val;
die("Option %s: Invalid value '%s'\n", arg->name, arg->val); die("Option %s: Invalid value '%s'\n", arg->name, arg->val);
return 0; return 0;
} }
int arg_parse_enum_or_int(const struct arg *arg) { int arg_parse_enum_or_int(const struct arg *arg) {
if (arg->def->enums) if (arg->def->enums) return arg_parse_enum(arg);
return arg_parse_enum(arg);
return arg_parse_int(arg); return arg_parse_int(arg);
} }

13
args.h
View File

@ -8,7 +8,6 @@
* be found in the AUTHORS file in the root of the source tree. * be found in the AUTHORS file in the root of the source tree.
*/ */
#ifndef ARGS_H_ #ifndef ARGS_H_
#define ARGS_H_ #define ARGS_H_
#include <stdio.h> #include <stdio.h>
@ -29,7 +28,8 @@ struct arg_enum_list {
const char *name; const char *name;
int val; int val;
}; };
#define ARG_ENUM_LIST_END {0} #define ARG_ENUM_LIST_END \
{ 0 }
typedef struct arg_def { typedef struct arg_def {
const char *short_name; const char *short_name;
@ -38,9 +38,12 @@ typedef struct arg_def {
const char *desc; const char *desc;
const struct arg_enum_list *enums; const struct arg_enum_list *enums;
} arg_def_t; } arg_def_t;
#define ARG_DEF(s,l,v,d) {s,l,v,d, NULL} #define ARG_DEF(s, l, v, d) \
#define ARG_DEF_ENUM(s,l,v,d,e) {s,l,v,d,e} { s, l, v, d, NULL }
#define ARG_DEF_LIST_END {0} #define ARG_DEF_ENUM(s, l, v, d, e) \
{ s, l, v, d, e }
#define ARG_DEF_LIST_END \
{ 0 }
struct arg arg_init(char **argv); struct arg arg_init(char **argv);
int arg_match(struct arg *arg_, const struct arg_def *def, char **argv); int arg_match(struct arg *arg_, const struct arg_def *def, char **argv);

View File

@ -46,7 +46,8 @@ int file_is_ivf(struct VpxInputContext *input_ctx) {
is_ivf = 1; is_ivf = 1;
if (mem_get_le16(raw_hdr + 4) != 0) { if (mem_get_le16(raw_hdr + 4) != 0) {
fprintf(stderr, "Error: Unrecognized IVF version! This file may not" fprintf(stderr,
"Error: Unrecognized IVF version! This file may not"
" decode properly."); " decode properly.");
} }
@ -69,14 +70,13 @@ int file_is_ivf(struct VpxInputContext *input_ctx) {
return is_ivf; return is_ivf;
} }
int ivf_read_frame(FILE *infile, uint8_t **buffer, int ivf_read_frame(FILE *infile, uint8_t **buffer, size_t *bytes_read,
size_t *bytes_read, size_t *buffer_size) { size_t *buffer_size) {
char raw_header[IVF_FRAME_HDR_SZ] = { 0 }; char raw_header[IVF_FRAME_HDR_SZ] = { 0 };
size_t frame_size = 0; size_t frame_size = 0;
if (fread(raw_header, IVF_FRAME_HDR_SZ, 1, infile) != 1) { if (fread(raw_header, IVF_FRAME_HDR_SZ, 1, infile) != 1) {
if (!feof(infile)) if (!feof(infile)) warn("Failed to read frame size\n");
warn("Failed to read frame size\n");
} else { } else {
frame_size = mem_get_le32(raw_header); frame_size = mem_get_le32(raw_header);

View File

@ -18,8 +18,8 @@ extern "C" {
int file_is_ivf(struct VpxInputContext *input); int file_is_ivf(struct VpxInputContext *input);
int ivf_read_frame(FILE *infile, uint8_t **buffer, int ivf_read_frame(FILE *infile, uint8_t **buffer, size_t *bytes_read,
size_t *bytes_read, size_t *buffer_size); size_t *buffer_size);
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */

View File

@ -13,10 +13,8 @@
#include "vpx/vpx_encoder.h" #include "vpx/vpx_encoder.h"
#include "vpx_ports/mem_ops.h" #include "vpx_ports/mem_ops.h"
void ivf_write_file_header(FILE *outfile, void ivf_write_file_header(FILE *outfile, const struct vpx_codec_enc_cfg *cfg,
const struct vpx_codec_enc_cfg *cfg, unsigned int fourcc, int frame_cnt) {
unsigned int fourcc,
int frame_cnt) {
char header[32]; char header[32];
header[0] = 'D'; header[0] = 'D';

View File

@ -19,10 +19,8 @@ struct vpx_codec_cx_pkt;
extern "C" { extern "C" {
#endif #endif
void ivf_write_file_header(FILE *outfile, void ivf_write_file_header(FILE *outfile, const struct vpx_codec_enc_cfg *cfg,
const struct vpx_codec_enc_cfg *cfg, uint32_t fourcc, int frame_cnt);
uint32_t fourcc,
int frame_cnt);
void ivf_write_frame_header(FILE *outfile, int64_t pts, size_t frame_size); void ivf_write_frame_header(FILE *outfile, int64_t pts, size_t frame_size);

View File

@ -24,15 +24,13 @@
#include "md5_utils.h" #include "md5_utils.h"
static void static void byteSwap(UWORD32 *buf, unsigned words) {
byteSwap(UWORD32 *buf, unsigned words) {
md5byte *p; md5byte *p;
/* Only swap bytes for big endian machines */ /* Only swap bytes for big endian machines */
int i = 1; int i = 1;
if (*(char *)&i == 1) if (*(char *)&i == 1) return;
return;
p = (md5byte *)buf; p = (md5byte *)buf;
@ -47,8 +45,7 @@ byteSwap(UWORD32 *buf, unsigned words) {
* Start MD5 accumulation. Set bit count to 0 and buffer to mysterious * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
* initialization constants. * initialization constants.
*/ */
void void MD5Init(struct MD5Context *ctx) {
MD5Init(struct MD5Context *ctx) {
ctx->buf[0] = 0x67452301; ctx->buf[0] = 0x67452301;
ctx->buf[1] = 0xefcdab89; ctx->buf[1] = 0xefcdab89;
ctx->buf[2] = 0x98badcfe; ctx->buf[2] = 0x98badcfe;
@ -62,8 +59,7 @@ MD5Init(struct MD5Context *ctx) {
* Update context to reflect the concatenation of another buffer full * Update context to reflect the concatenation of another buffer full
* of bytes. * of bytes.
*/ */
void void MD5Update(struct MD5Context *ctx, md5byte const *buf, unsigned len) {
MD5Update(struct MD5Context *ctx, md5byte const *buf, unsigned len) {
UWORD32 t; UWORD32 t;
/* Update byte count */ /* Update byte count */
@ -104,8 +100,7 @@ MD5Update(struct MD5Context *ctx, md5byte const *buf, unsigned len) {
* Final wrapup - pad to 64-byte boundary with the bit pattern * Final wrapup - pad to 64-byte boundary with the bit pattern
* 1 0* (64-bit count of bits processed, MSB-first) * 1 0* (64-bit count of bits processed, MSB-first)
*/ */
void void MD5Final(md5byte digest[16], struct MD5Context *ctx) {
MD5Final(md5byte digest[16], struct MD5Context *ctx) {
int count = ctx->bytes[0] & 0x3f; /* Number of bytes in ctx->in */ int count = ctx->bytes[0] & 0x3f; /* Number of bytes in ctx->in */
md5byte *p = (md5byte *)ctx->in + count; md5byte *p = (md5byte *)ctx->in + count;
@ -166,8 +161,8 @@ MD5Final(md5byte digest[16], struct MD5Context *ctx) {
* reflect the addition of 16 longwords of new data. MD5Update blocks * reflect the addition of 16 longwords of new data. MD5Update blocks
* the data and converts bytes into longwords for this routine. * the data and converts bytes into longwords for this routine.
*/ */
VPX_NO_UNSIGNED_OVERFLOW_CHECK void VPX_NO_UNSIGNED_OVERFLOW_CHECK void MD5Transform(UWORD32 buf[4],
MD5Transform(UWORD32 buf[4], UWORD32 const in[16]) { UWORD32 const in[16]) {
register UWORD32 a, b, c, d; register UWORD32 a, b, c, d;
a = buf[0]; a = buf[0];

View File

@ -45,8 +45,7 @@ struct rate_hist *init_rate_histogram(const vpx_codec_enc_cfg_t *cfg,
hist->samples = cfg->rc_buf_sz * 5 / 4 * fps->num / fps->den / 1000; hist->samples = cfg->rc_buf_sz * 5 / 4 * fps->num / fps->den / 1000;
// prevent division by zero // prevent division by zero
if (hist->samples == 0) if (hist->samples == 0) hist->samples = 1;
hist->samples = 1;
hist->frames = 0; hist->frames = 0;
hist->total = 0; hist->total = 0;
@ -85,11 +84,9 @@ void update_rate_histogram(struct rate_hist *hist,
hist->pts[idx] = now; hist->pts[idx] = now;
hist->sz[idx] = (int)pkt->data.frame.sz; hist->sz[idx] = (int)pkt->data.frame.sz;
if (now < cfg->rc_buf_initial_sz) if (now < cfg->rc_buf_initial_sz) return;
return;
if (!cfg->rc_target_bitrate) if (!cfg->rc_target_bitrate) return;
return;
then = now; then = now;
@ -98,20 +95,16 @@ void update_rate_histogram(struct rate_hist *hist,
const int i_idx = (i - 1) % hist->samples; const int i_idx = (i - 1) % hist->samples;
then = hist->pts[i_idx]; then = hist->pts[i_idx];
if (now - then > cfg->rc_buf_sz) if (now - then > cfg->rc_buf_sz) break;
break;
sum_sz += hist->sz[i_idx]; sum_sz += hist->sz[i_idx];
} }
if (now == then) if (now == then) return;
return;
avg_bitrate = sum_sz * 8 * 1000 / (now - then); avg_bitrate = sum_sz * 8 * 1000 / (now - then);
idx = (int)(avg_bitrate * (RATE_BINS / 2) / (cfg->rc_target_bitrate * 1000)); idx = (int)(avg_bitrate * (RATE_BINS / 2) / (cfg->rc_target_bitrate * 1000));
if (idx < 0) if (idx < 0) idx = 0;
idx = 0; if (idx > RATE_BINS - 1) idx = RATE_BINS - 1;
if (idx > RATE_BINS - 1)
idx = RATE_BINS - 1;
if (hist->bucket[idx].low > avg_bitrate) if (hist->bucket[idx].low > avg_bitrate)
hist->bucket[idx].low = (int)avg_bitrate; hist->bucket[idx].low = (int)avg_bitrate;
if (hist->bucket[idx].high < avg_bitrate) if (hist->bucket[idx].high < avg_bitrate)
@ -120,8 +113,8 @@ void update_rate_histogram(struct rate_hist *hist,
hist->total++; hist->total++;
} }
static int merge_hist_buckets(struct hist_bucket *bucket, static int merge_hist_buckets(struct hist_bucket *bucket, int max_buckets,
int max_buckets, int *num_buckets) { int *num_buckets) {
int small_bucket = 0, merge_bucket = INT_MAX, big_bucket = 0; int small_bucket = 0, merge_bucket = INT_MAX, big_bucket = 0;
int buckets = *num_buckets; int buckets = *num_buckets;
int i; int i;
@ -129,10 +122,8 @@ static int merge_hist_buckets(struct hist_bucket *bucket,
/* Find the extrema for this list of buckets */ /* Find the extrema for this list of buckets */
big_bucket = small_bucket = 0; big_bucket = small_bucket = 0;
for (i = 0; i < buckets; i++) { for (i = 0; i < buckets; i++) {
if (bucket[i].count < bucket[small_bucket].count) if (bucket[i].count < bucket[small_bucket].count) small_bucket = i;
small_bucket = i; if (bucket[i].count > bucket[big_bucket].count) big_bucket = i;
if (bucket[i].count > bucket[big_bucket].count)
big_bucket = i;
} }
/* If we have too many buckets, merge the smallest with an adjacent /* If we have too many buckets, merge the smallest with an adjacent
@ -174,13 +165,10 @@ static int merge_hist_buckets(struct hist_bucket *bucket,
*/ */
big_bucket = small_bucket = 0; big_bucket = small_bucket = 0;
for (i = 0; i < buckets; i++) { for (i = 0; i < buckets; i++) {
if (i > merge_bucket) if (i > merge_bucket) bucket[i] = bucket[i + 1];
bucket[i] = bucket[i + 1];
if (bucket[i].count < bucket[small_bucket].count) if (bucket[i].count < bucket[small_bucket].count) small_bucket = i;
small_bucket = i; if (bucket[i].count > bucket[big_bucket].count) big_bucket = i;
if (bucket[i].count > bucket[big_bucket].count)
big_bucket = i;
} }
} }
@ -188,8 +176,8 @@ static int merge_hist_buckets(struct hist_bucket *bucket,
return bucket[big_bucket].count; return bucket[big_bucket].count;
} }
static void show_histogram(const struct hist_bucket *bucket, static void show_histogram(const struct hist_bucket *bucket, int buckets,
int buckets, int total, int scale) { int total, int scale) {
const char *pat1, *pat2; const char *pat1, *pat2;
int i; int i;
@ -232,8 +220,7 @@ static void show_histogram(const struct hist_bucket *bucket,
pct = (float)(100.0 * bucket[i].count / total); pct = (float)(100.0 * bucket[i].count / total);
len = HIST_BAR_MAX * bucket[i].count / scale; len = HIST_BAR_MAX * bucket[i].count / scale;
if (len < 1) if (len < 1) len = 1;
len = 1;
assert(len <= HIST_BAR_MAX); assert(len <= HIST_BAR_MAX);
if (bucket[i].low == bucket[i].high) if (bucket[i].low == bucket[i].high)
@ -241,8 +228,7 @@ static void show_histogram(const struct hist_bucket *bucket,
else else
fprintf(stderr, pat2, bucket[i].low, bucket[i].high); fprintf(stderr, pat2, bucket[i].low, bucket[i].high);
for (j = 0; j < HIST_BAR_MAX; j++) for (j = 0; j < HIST_BAR_MAX; j++) fprintf(stderr, j < len ? "=" : " ");
fprintf(stderr, j < len ? "=" : " ");
fprintf(stderr, "\t%5d (%6.2f%%)\n", bucket[i].count, pct); fprintf(stderr, "\t%5d (%6.2f%%)\n", bucket[i].count, pct);
} }
} }
@ -268,14 +254,13 @@ void show_q_histogram(const int counts[64], int max_buckets) {
show_histogram(bucket, buckets, total, scale); show_histogram(bucket, buckets, total, scale);
} }
void show_rate_histogram(struct rate_hist *hist, void show_rate_histogram(struct rate_hist *hist, const vpx_codec_enc_cfg_t *cfg,
const vpx_codec_enc_cfg_t *cfg, int max_buckets) { int max_buckets) {
int i, scale; int i, scale;
int buckets = 0; int buckets = 0;
for (i = 0; i < RATE_BINS; i++) { for (i = 0; i < RATE_BINS; i++) {
if (hist->bucket[i].low == INT_MAX) if (hist->bucket[i].low == INT_MAX) continue;
continue;
hist->bucket[buckets++] = hist->bucket[i]; hist->bucket[buckets++] = hist->bucket[i];
} }

View File

@ -35,18 +35,17 @@
#endif #endif
#endif #endif
#define LOG_ERROR(label) do {\ #define LOG_ERROR(label) \
do { \
const char *l = label; \ const char *l = label; \
va_list ap; \ va_list ap; \
va_start(ap, fmt); \ va_start(ap, fmt); \
if (l)\ if (l) fprintf(stderr, "%s: ", l); \
fprintf(stderr, "%s: ", l);\
vfprintf(stderr, fmt, ap); \ vfprintf(stderr, fmt, ap); \
fprintf(stderr, "\n"); \ fprintf(stderr, "\n"); \
va_end(ap); \ va_end(ap); \
} while (0) } while (0)
FILE *set_binary_mode(FILE *stream) { FILE *set_binary_mode(FILE *stream) {
(void)stream; (void)stream;
#if defined(_WIN32) || defined(__OS2__) #if defined(_WIN32) || defined(__OS2__)
@ -65,16 +64,13 @@ void fatal(const char *fmt, ...) {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
void warn(const char *fmt, ...) { void warn(const char *fmt, ...) { LOG_ERROR("Warning"); }
LOG_ERROR("Warning");
}
void die_codec(vpx_codec_ctx_t *ctx, const char *s) { void die_codec(vpx_codec_ctx_t *ctx, const char *s) {
const char *detail = vpx_codec_error_detail(ctx); const char *detail = vpx_codec_error_detail(ctx);
printf("%s: %s\n", s, vpx_codec_error(ctx)); printf("%s: %s\n", s, vpx_codec_error(ctx));
if (detail) if (detail) printf(" %s\n", detail);
printf(" %s\n", detail);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -97,15 +93,16 @@ int read_yuv_frame(struct VpxInputContext *input_ctx, vpx_image_t *yuv_frame) {
*/ */
switch (plane) { switch (plane) {
case 1: case 1:
ptr = yuv_frame->planes[ ptr =
yuv_frame->fmt == VPX_IMG_FMT_YV12 ? VPX_PLANE_V : VPX_PLANE_U]; yuv_frame->planes[yuv_frame->fmt == VPX_IMG_FMT_YV12 ? VPX_PLANE_V
: VPX_PLANE_U];
break; break;
case 2: case 2:
ptr = yuv_frame->planes[ ptr =
yuv_frame->fmt == VPX_IMG_FMT_YV12 ? VPX_PLANE_U : VPX_PLANE_V]; yuv_frame->planes[yuv_frame->fmt == VPX_IMG_FMT_YV12 ? VPX_PLANE_U
: VPX_PLANE_V];
break; break;
default: default: ptr = yuv_frame->planes[plane];
ptr = yuv_frame->planes[plane];
} }
for (r = 0; r < h; ++r) { for (r = 0; r < h; ++r) {
@ -146,17 +143,14 @@ int get_vpx_encoder_count(void) {
return sizeof(vpx_encoders) / sizeof(vpx_encoders[0]); return sizeof(vpx_encoders) / sizeof(vpx_encoders[0]);
} }
const VpxInterface *get_vpx_encoder_by_index(int i) { const VpxInterface *get_vpx_encoder_by_index(int i) { return &vpx_encoders[i]; }
return &vpx_encoders[i];
}
const VpxInterface *get_vpx_encoder_by_name(const char *name) { const VpxInterface *get_vpx_encoder_by_name(const char *name) {
int i; int i;
for (i = 0; i < get_vpx_encoder_count(); ++i) { for (i = 0; i < get_vpx_encoder_count(); ++i) {
const VpxInterface *encoder = get_vpx_encoder_by_index(i); const VpxInterface *encoder = get_vpx_encoder_by_index(i);
if (strcmp(encoder->name, name) == 0) if (strcmp(encoder->name, name) == 0) return encoder;
return encoder;
} }
return NULL; return NULL;
@ -180,17 +174,14 @@ int get_vpx_decoder_count(void) {
return sizeof(vpx_decoders) / sizeof(vpx_decoders[0]); return sizeof(vpx_decoders) / sizeof(vpx_decoders[0]);
} }
const VpxInterface *get_vpx_decoder_by_index(int i) { const VpxInterface *get_vpx_decoder_by_index(int i) { return &vpx_decoders[i]; }
return &vpx_decoders[i];
}
const VpxInterface *get_vpx_decoder_by_name(const char *name) { const VpxInterface *get_vpx_decoder_by_name(const char *name) {
int i; int i;
for (i = 0; i < get_vpx_decoder_count(); ++i) { for (i = 0; i < get_vpx_decoder_count(); ++i) {
const VpxInterface *const decoder = get_vpx_decoder_by_index(i); const VpxInterface *const decoder = get_vpx_decoder_by_index(i);
if (strcmp(decoder->name, name) == 0) if (strcmp(decoder->name, name) == 0) return decoder;
return decoder;
} }
return NULL; return NULL;
@ -201,8 +192,7 @@ const VpxInterface *get_vpx_decoder_by_fourcc(uint32_t fourcc) {
for (i = 0; i < get_vpx_decoder_count(); ++i) { for (i = 0; i < get_vpx_decoder_count(); ++i) {
const VpxInterface *const decoder = get_vpx_decoder_by_index(i); const VpxInterface *const decoder = get_vpx_decoder_by_index(i);
if (decoder->fourcc == fourcc) if (decoder->fourcc == fourcc) return decoder;
return decoder;
} }
return NULL; return NULL;
@ -256,8 +246,7 @@ int vpx_img_read(vpx_image_t *img, FILE *file) {
int y; int y;
for (y = 0; y < h; ++y) { for (y = 0; y < h; ++y) {
if (fread(buf, 1, w, file) != (size_t)w) if (fread(buf, 1, w, file) != (size_t)w) return 0;
return 0;
buf += stride; buf += stride;
} }
} }
@ -286,19 +275,16 @@ static void highbd_img_upshift(vpx_image_t *dst, vpx_image_t *src,
int plane; int plane;
if (dst->d_w != src->d_w || dst->d_h != src->d_h || if (dst->d_w != src->d_w || dst->d_h != src->d_h ||
dst->x_chroma_shift != src->x_chroma_shift || dst->x_chroma_shift != src->x_chroma_shift ||
dst->y_chroma_shift != src->y_chroma_shift || dst->y_chroma_shift != src->y_chroma_shift || dst->fmt != src->fmt ||
dst->fmt != src->fmt || input_shift < 0) { input_shift < 0) {
fatal("Unsupported image conversion"); fatal("Unsupported image conversion");
} }
switch (src->fmt) { switch (src->fmt) {
case VPX_IMG_FMT_I42016: case VPX_IMG_FMT_I42016:
case VPX_IMG_FMT_I42216: case VPX_IMG_FMT_I42216:
case VPX_IMG_FMT_I44416: case VPX_IMG_FMT_I44416:
case VPX_IMG_FMT_I44016: case VPX_IMG_FMT_I44016: break;
break; default: fatal("Unsupported image conversion"); break;
default:
fatal("Unsupported image conversion");
break;
} }
for (plane = 0; plane < 3; plane++) { for (plane = 0; plane < 3; plane++) {
int w = src->d_w; int w = src->d_w;
@ -313,8 +299,7 @@ static void highbd_img_upshift(vpx_image_t *dst, vpx_image_t *src,
(uint16_t *)(src->planes[plane] + y * src->stride[plane]); (uint16_t *)(src->planes[plane] + y * src->stride[plane]);
uint16_t *p_dst = uint16_t *p_dst =
(uint16_t *)(dst->planes[plane] + y * dst->stride[plane]); (uint16_t *)(dst->planes[plane] + y * dst->stride[plane]);
for (x = 0; x < w; x++) for (x = 0; x < w; x++) *p_dst++ = (*p_src++ << input_shift) + offset;
*p_dst++ = (*p_src++ << input_shift) + offset;
} }
} }
} }
@ -327,19 +312,15 @@ static void lowbd_img_upshift(vpx_image_t *dst, vpx_image_t *src,
if (dst->d_w != src->d_w || dst->d_h != src->d_h || if (dst->d_w != src->d_w || dst->d_h != src->d_h ||
dst->x_chroma_shift != src->x_chroma_shift || dst->x_chroma_shift != src->x_chroma_shift ||
dst->y_chroma_shift != src->y_chroma_shift || dst->y_chroma_shift != src->y_chroma_shift ||
dst->fmt != src->fmt + VPX_IMG_FMT_HIGHBITDEPTH || dst->fmt != src->fmt + VPX_IMG_FMT_HIGHBITDEPTH || input_shift < 0) {
input_shift < 0) {
fatal("Unsupported image conversion"); fatal("Unsupported image conversion");
} }
switch (src->fmt) { switch (src->fmt) {
case VPX_IMG_FMT_I420: case VPX_IMG_FMT_I420:
case VPX_IMG_FMT_I422: case VPX_IMG_FMT_I422:
case VPX_IMG_FMT_I444: case VPX_IMG_FMT_I444:
case VPX_IMG_FMT_I440: case VPX_IMG_FMT_I440: break;
break; default: fatal("Unsupported image conversion"); break;
default:
fatal("Unsupported image conversion");
break;
} }
for (plane = 0; plane < 3; plane++) { for (plane = 0; plane < 3; plane++) {
int w = src->d_w; int w = src->d_w;
@ -360,8 +341,7 @@ static void lowbd_img_upshift(vpx_image_t *dst, vpx_image_t *src,
} }
} }
void vpx_img_upshift(vpx_image_t *dst, vpx_image_t *src, void vpx_img_upshift(vpx_image_t *dst, vpx_image_t *src, int input_shift) {
int input_shift) {
if (src->fmt & VPX_IMG_FMT_HIGHBITDEPTH) { if (src->fmt & VPX_IMG_FMT_HIGHBITDEPTH) {
highbd_img_upshift(dst, src, input_shift); highbd_img_upshift(dst, src, input_shift);
} else { } else {
@ -371,9 +351,8 @@ void vpx_img_upshift(vpx_image_t *dst, vpx_image_t *src,
void vpx_img_truncate_16_to_8(vpx_image_t *dst, vpx_image_t *src) { void vpx_img_truncate_16_to_8(vpx_image_t *dst, vpx_image_t *src) {
int plane; int plane;
if (dst->fmt + VPX_IMG_FMT_HIGHBITDEPTH != src->fmt || if (dst->fmt + VPX_IMG_FMT_HIGHBITDEPTH != src->fmt || dst->d_w != src->d_w ||
dst->d_w != src->d_w || dst->d_h != src->d_h || dst->d_h != src->d_h || dst->x_chroma_shift != src->x_chroma_shift ||
dst->x_chroma_shift != src->x_chroma_shift ||
dst->y_chroma_shift != src->y_chroma_shift) { dst->y_chroma_shift != src->y_chroma_shift) {
fatal("Unsupported image conversion"); fatal("Unsupported image conversion");
} }
@ -381,11 +360,8 @@ void vpx_img_truncate_16_to_8(vpx_image_t *dst, vpx_image_t *src) {
case VPX_IMG_FMT_I420: case VPX_IMG_FMT_I420:
case VPX_IMG_FMT_I422: case VPX_IMG_FMT_I422:
case VPX_IMG_FMT_I444: case VPX_IMG_FMT_I444:
case VPX_IMG_FMT_I440: case VPX_IMG_FMT_I440: break;
break; default: fatal("Unsupported image conversion"); break;
default:
fatal("Unsupported image conversion");
break;
} }
for (plane = 0; plane < 3; plane++) { for (plane = 0; plane < 3; plane++) {
int w = src->d_w; int w = src->d_w;
@ -411,19 +387,16 @@ static void highbd_img_downshift(vpx_image_t *dst, vpx_image_t *src,
int plane; int plane;
if (dst->d_w != src->d_w || dst->d_h != src->d_h || if (dst->d_w != src->d_w || dst->d_h != src->d_h ||
dst->x_chroma_shift != src->x_chroma_shift || dst->x_chroma_shift != src->x_chroma_shift ||
dst->y_chroma_shift != src->y_chroma_shift || dst->y_chroma_shift != src->y_chroma_shift || dst->fmt != src->fmt ||
dst->fmt != src->fmt || down_shift < 0) { down_shift < 0) {
fatal("Unsupported image conversion"); fatal("Unsupported image conversion");
} }
switch (src->fmt) { switch (src->fmt) {
case VPX_IMG_FMT_I42016: case VPX_IMG_FMT_I42016:
case VPX_IMG_FMT_I42216: case VPX_IMG_FMT_I42216:
case VPX_IMG_FMT_I44416: case VPX_IMG_FMT_I44416:
case VPX_IMG_FMT_I44016: case VPX_IMG_FMT_I44016: break;
break; default: fatal("Unsupported image conversion"); break;
default:
fatal("Unsupported image conversion");
break;
} }
for (plane = 0; plane < 3; plane++) { for (plane = 0; plane < 3; plane++) {
int w = src->d_w; int w = src->d_w;
@ -438,8 +411,7 @@ static void highbd_img_downshift(vpx_image_t *dst, vpx_image_t *src,
(uint16_t *)(src->planes[plane] + y * src->stride[plane]); (uint16_t *)(src->planes[plane] + y * src->stride[plane]);
uint16_t *p_dst = uint16_t *p_dst =
(uint16_t *)(dst->planes[plane] + y * dst->stride[plane]); (uint16_t *)(dst->planes[plane] + y * dst->stride[plane]);
for (x = 0; x < w; x++) for (x = 0; x < w; x++) *p_dst++ = *p_src++ >> down_shift;
*p_dst++ = *p_src++ >> down_shift;
} }
} }
} }
@ -450,19 +422,15 @@ static void lowbd_img_downshift(vpx_image_t *dst, vpx_image_t *src,
if (dst->d_w != src->d_w || dst->d_h != src->d_h || if (dst->d_w != src->d_w || dst->d_h != src->d_h ||
dst->x_chroma_shift != src->x_chroma_shift || dst->x_chroma_shift != src->x_chroma_shift ||
dst->y_chroma_shift != src->y_chroma_shift || dst->y_chroma_shift != src->y_chroma_shift ||
src->fmt != dst->fmt + VPX_IMG_FMT_HIGHBITDEPTH || src->fmt != dst->fmt + VPX_IMG_FMT_HIGHBITDEPTH || down_shift < 0) {
down_shift < 0) {
fatal("Unsupported image conversion"); fatal("Unsupported image conversion");
} }
switch (dst->fmt) { switch (dst->fmt) {
case VPX_IMG_FMT_I420: case VPX_IMG_FMT_I420:
case VPX_IMG_FMT_I422: case VPX_IMG_FMT_I422:
case VPX_IMG_FMT_I444: case VPX_IMG_FMT_I444:
case VPX_IMG_FMT_I440: case VPX_IMG_FMT_I440: break;
break; default: fatal("Unsupported image conversion"); break;
default:
fatal("Unsupported image conversion");
break;
} }
for (plane = 0; plane < 3; plane++) { for (plane = 0; plane < 3; plane++) {
int w = src->d_w; int w = src->d_w;
@ -483,8 +451,7 @@ static void lowbd_img_downshift(vpx_image_t *dst, vpx_image_t *src,
} }
} }
void vpx_img_downshift(vpx_image_t *dst, vpx_image_t *src, void vpx_img_downshift(vpx_image_t *dst, vpx_image_t *src, int down_shift) {
int down_shift) {
if (dst->fmt & VPX_IMG_FMT_HIGHBITDEPTH) { if (dst->fmt & VPX_IMG_FMT_HIGHBITDEPTH) {
highbd_img_downshift(dst, src, down_shift); highbd_img_downshift(dst, src, down_shift);
} else { } else {

View File

@ -30,21 +30,17 @@ VpxVideoReader *vpx_video_reader_open(const char *filename) {
char header[32]; char header[32];
VpxVideoReader *reader = NULL; VpxVideoReader *reader = NULL;
FILE *const file = fopen(filename, "rb"); FILE *const file = fopen(filename, "rb");
if (!file) if (!file) return NULL; // Can't open file
return NULL; // Can't open file
if (fread(header, 1, 32, file) != 32) if (fread(header, 1, 32, file) != 32) return NULL; // Can't read file header
return NULL; // Can't read file header
if (memcmp(kIVFSignature, header, 4) != 0) if (memcmp(kIVFSignature, header, 4) != 0)
return NULL; // Wrong IVF signature return NULL; // Wrong IVF signature
if (mem_get_le16(header + 4) != 0) if (mem_get_le16(header + 4) != 0) return NULL; // Wrong IVF version
return NULL; // Wrong IVF version
reader = calloc(1, sizeof(*reader)); reader = calloc(1, sizeof(*reader));
if (!reader) if (!reader) return NULL; // Can't allocate VpxVideoReader
return NULL; // Can't allocate VpxVideoReader
reader->file = file; reader->file = file;
reader->info.codec_fourcc = mem_get_le32(header + 8); reader->info.codec_fourcc = mem_get_le32(header + 8);
@ -71,8 +67,7 @@ int vpx_video_reader_read_frame(VpxVideoReader *reader) {
const uint8_t *vpx_video_reader_get_frame(VpxVideoReader *reader, const uint8_t *vpx_video_reader_get_frame(VpxVideoReader *reader,
size_t *size) { size_t *size) {
if (size) if (size) *size = reader->frame_size;
*size = reader->frame_size;
return reader->buffer; return reader->buffer;
} }
@ -80,4 +75,3 @@ const uint8_t *vpx_video_reader_get_frame(VpxVideoReader *reader,
const VpxVideoInfo *vpx_video_reader_get_info(VpxVideoReader *reader) { const VpxVideoInfo *vpx_video_reader_get_info(VpxVideoReader *reader) {
return &reader->info; return &reader->info;
} }

View File

@ -39,8 +39,7 @@ int vpx_video_reader_read_frame(VpxVideoReader *reader);
// Returns the pointer to memory buffer with frame data read by last call to // Returns the pointer to memory buffer with frame data read by last call to
// vpx_video_reader_read_frame(). // vpx_video_reader_read_frame().
const uint8_t *vpx_video_reader_get_frame(VpxVideoReader *reader, const uint8_t *vpx_video_reader_get_frame(VpxVideoReader *reader, size_t *size);
size_t *size);
// Fills VpxVideoInfo with information from opened video file. // Fills VpxVideoInfo with information from opened video file.
const VpxVideoInfo *vpx_video_reader_get_info(VpxVideoReader *reader); const VpxVideoInfo *vpx_video_reader_get_info(VpxVideoReader *reader);

View File

@ -37,12 +37,10 @@ VpxVideoWriter *vpx_video_writer_open(const char *filename,
if (container == kContainerIVF) { if (container == kContainerIVF) {
VpxVideoWriter *writer = NULL; VpxVideoWriter *writer = NULL;
FILE *const file = fopen(filename, "wb"); FILE *const file = fopen(filename, "wb");
if (!file) if (!file) return NULL;
return NULL;
writer = malloc(sizeof(*writer)); writer = malloc(sizeof(*writer));
if (!writer) if (!writer) return NULL;
return NULL;
writer->frame_count = 0; writer->frame_count = 0;
writer->info = *info; writer->info = *info;
@ -67,12 +65,10 @@ void vpx_video_writer_close(VpxVideoWriter *writer) {
} }
} }
int vpx_video_writer_write_frame(VpxVideoWriter *writer, int vpx_video_writer_write_frame(VpxVideoWriter *writer, const uint8_t *buffer,
const uint8_t *buffer, size_t size, size_t size, int64_t pts) {
int64_t pts) {
ivf_write_frame_header(writer->file, pts, size); ivf_write_frame_header(writer->file, pts, size);
if (fwrite(buffer, 1, size, writer->file) != size) if (fwrite(buffer, 1, size, writer->file) != size) return 0;
return 0;
++writer->frame_count; ++writer->frame_count;

View File

@ -13,9 +13,7 @@
#include "./video_common.h" #include "./video_common.h"
typedef enum { typedef enum { kContainerIVF } VpxContainer;
kContainerIVF
} VpxContainer;
struct VpxVideoWriterStruct; struct VpxVideoWriterStruct;
typedef struct VpxVideoWriterStruct VpxVideoWriter; typedef struct VpxVideoWriterStruct VpxVideoWriter;
@ -36,9 +34,8 @@ VpxVideoWriter *vpx_video_writer_open(const char *filename,
void vpx_video_writer_close(VpxVideoWriter *writer); void vpx_video_writer_close(VpxVideoWriter *writer);
// Writes frame bytes to the file. // Writes frame bytes to the file.
int vpx_video_writer_write_frame(VpxVideoWriter *writer, int vpx_video_writer_write_frame(VpxVideoWriter *writer, const uint8_t *buffer,
const uint8_t *buffer, size_t size, size_t size, int64_t pts);
int64_t pts);
#ifdef __cplusplus #ifdef __cplusplus
} // extern "C" } // extern "C"

417
vpxdec.c
View File

@ -47,90 +47,108 @@ struct VpxDecInputContext {
struct WebmInputContext *webm_ctx; struct WebmInputContext *webm_ctx;
}; };
static const arg_def_t looparg = ARG_DEF( static const arg_def_t looparg =
NULL, "loops", 1, "Number of times to decode the file"); ARG_DEF(NULL, "loops", 1, "Number of times to decode the file");
static const arg_def_t codecarg = ARG_DEF( static const arg_def_t codecarg = ARG_DEF(NULL, "codec", 1, "Codec to use");
NULL, "codec", 1, "Codec to use"); static const arg_def_t use_yv12 =
static const arg_def_t use_yv12 = ARG_DEF( ARG_DEF(NULL, "yv12", 0, "Output raw YV12 frames");
NULL, "yv12", 0, "Output raw YV12 frames"); static const arg_def_t use_i420 =
static const arg_def_t use_i420 = ARG_DEF( ARG_DEF(NULL, "i420", 0, "Output raw I420 frames");
NULL, "i420", 0, "Output raw I420 frames"); static const arg_def_t flipuvarg =
static const arg_def_t flipuvarg = ARG_DEF( ARG_DEF(NULL, "flipuv", 0, "Flip the chroma planes in the output");
NULL, "flipuv", 0, "Flip the chroma planes in the output"); static const arg_def_t rawvideo =
static const arg_def_t rawvideo = ARG_DEF( ARG_DEF(NULL, "rawvideo", 0, "Output raw YUV frames");
NULL, "rawvideo", 0, "Output raw YUV frames"); static const arg_def_t noblitarg =
static const arg_def_t noblitarg = ARG_DEF( ARG_DEF(NULL, "noblit", 0, "Don't process the decoded frames");
NULL, "noblit", 0, "Don't process the decoded frames"); static const arg_def_t progressarg =
static const arg_def_t progressarg = ARG_DEF( ARG_DEF(NULL, "progress", 0, "Show progress after each frame decodes");
NULL, "progress", 0, "Show progress after each frame decodes"); static const arg_def_t limitarg =
static const arg_def_t limitarg = ARG_DEF( ARG_DEF(NULL, "limit", 1, "Stop decoding after n frames");
NULL, "limit", 1, "Stop decoding after n frames"); static const arg_def_t skiparg =
static const arg_def_t skiparg = ARG_DEF( ARG_DEF(NULL, "skip", 1, "Skip the first n input frames");
NULL, "skip", 1, "Skip the first n input frames"); static const arg_def_t postprocarg =
static const arg_def_t postprocarg = ARG_DEF( ARG_DEF(NULL, "postproc", 0, "Postprocess decoded frames");
NULL, "postproc", 0, "Postprocess decoded frames"); static const arg_def_t summaryarg =
static const arg_def_t summaryarg = ARG_DEF( ARG_DEF(NULL, "summary", 0, "Show timing summary");
NULL, "summary", 0, "Show timing summary"); static const arg_def_t outputfile =
static const arg_def_t outputfile = ARG_DEF( ARG_DEF("o", "output", 1, "Output file name pattern (see below)");
"o", "output", 1, "Output file name pattern (see below)"); static const arg_def_t threadsarg =
static const arg_def_t threadsarg = ARG_DEF( ARG_DEF("t", "threads", 1, "Max threads to use");
"t", "threads", 1, "Max threads to use"); static const arg_def_t frameparallelarg =
static const arg_def_t frameparallelarg = ARG_DEF( ARG_DEF(NULL, "frame-parallel", 0, "Frame parallel decode");
NULL, "frame-parallel", 0, "Frame parallel decode"); static const arg_def_t verbosearg =
static const arg_def_t verbosearg = ARG_DEF( ARG_DEF("v", "verbose", 0, "Show version string");
"v", "verbose", 0, "Show version string"); static const arg_def_t error_concealment =
static const arg_def_t error_concealment = ARG_DEF( ARG_DEF(NULL, "error-concealment", 0, "Enable decoder error-concealment");
NULL, "error-concealment", 0, "Enable decoder error-concealment"); static const arg_def_t scalearg =
static const arg_def_t scalearg = ARG_DEF( ARG_DEF("S", "scale", 0, "Scale output frames uniformly");
"S", "scale", 0, "Scale output frames uniformly"); static const arg_def_t continuearg =
static const arg_def_t continuearg = ARG_DEF( ARG_DEF("k", "keep-going", 0, "(debug) Continue decoding after error");
"k", "keep-going", 0, "(debug) Continue decoding after error"); static const arg_def_t fb_arg =
static const arg_def_t fb_arg = ARG_DEF( ARG_DEF(NULL, "frame-buffers", 1, "Number of frame buffers to use");
NULL, "frame-buffers", 1, "Number of frame buffers to use"); static const arg_def_t md5arg =
static const arg_def_t md5arg = ARG_DEF( ARG_DEF(NULL, "md5", 0, "Compute the MD5 sum of the decoded frame");
NULL, "md5", 0, "Compute the MD5 sum of the decoded frame");
#if CONFIG_VP9_HIGHBITDEPTH #if CONFIG_VP9_HIGHBITDEPTH
static const arg_def_t outbitdeptharg = ARG_DEF( static const arg_def_t outbitdeptharg =
NULL, "output-bit-depth", 1, "Output bit-depth for decoded frames"); ARG_DEF(NULL, "output-bit-depth", 1, "Output bit-depth for decoded frames");
#endif #endif
static const arg_def_t *all_args[] = { static const arg_def_t *all_args[] = { &codecarg,
&codecarg, &use_yv12, &use_i420, &flipuvarg, &rawvideo, &noblitarg, &use_yv12,
&progressarg, &limitarg, &skiparg, &postprocarg, &summaryarg, &outputfile, &use_i420,
&threadsarg, &frameparallelarg, &verbosearg, &scalearg, &fb_arg, &flipuvarg,
&md5arg, &error_concealment, &continuearg, &rawvideo,
&noblitarg,
&progressarg,
&limitarg,
&skiparg,
&postprocarg,
&summaryarg,
&outputfile,
&threadsarg,
&frameparallelarg,
&verbosearg,
&scalearg,
&fb_arg,
&md5arg,
&error_concealment,
&continuearg,
#if CONFIG_VP9_HIGHBITDEPTH #if CONFIG_VP9_HIGHBITDEPTH
&outbitdeptharg, &outbitdeptharg,
#endif #endif
NULL NULL };
};
#if CONFIG_VP8_DECODER #if CONFIG_VP8_DECODER
static const arg_def_t addnoise_level = ARG_DEF( static const arg_def_t addnoise_level =
NULL, "noise-level", 1, "Enable VP8 postproc add noise"); ARG_DEF(NULL, "noise-level", 1, "Enable VP8 postproc add noise");
static const arg_def_t deblock = ARG_DEF( static const arg_def_t deblock =
NULL, "deblock", 0, "Enable VP8 deblocking"); ARG_DEF(NULL, "deblock", 0, "Enable VP8 deblocking");
static const arg_def_t demacroblock_level = ARG_DEF( static const arg_def_t demacroblock_level = ARG_DEF(
NULL, "demacroblock-level", 1, "Enable VP8 demacroblocking, w/ level"); NULL, "demacroblock-level", 1, "Enable VP8 demacroblocking, w/ level");
static const arg_def_t pp_debug_info = ARG_DEF( static const arg_def_t pp_debug_info =
NULL, "pp-debug-info", 1, "Enable VP8 visible debug info"); ARG_DEF(NULL, "pp-debug-info", 1, "Enable VP8 visible debug info");
static const arg_def_t pp_disp_ref_frame = ARG_DEF( static const arg_def_t pp_disp_ref_frame =
NULL, "pp-dbg-ref-frame", 1, ARG_DEF(NULL, "pp-dbg-ref-frame", 1,
"Display only selected reference frame per macro block"); "Display only selected reference frame per macro block");
static const arg_def_t pp_disp_mb_modes = ARG_DEF( static const arg_def_t pp_disp_mb_modes = ARG_DEF(
NULL, "pp-dbg-mb-modes", 1, "Display only selected macro block modes"); NULL, "pp-dbg-mb-modes", 1, "Display only selected macro block modes");
static const arg_def_t pp_disp_b_modes = ARG_DEF( static const arg_def_t pp_disp_b_modes =
NULL, "pp-dbg-b-modes", 1, "Display only selected block modes"); ARG_DEF(NULL, "pp-dbg-b-modes", 1, "Display only selected block modes");
static const arg_def_t pp_disp_mvs = ARG_DEF( static const arg_def_t pp_disp_mvs =
NULL, "pp-dbg-mvs", 1, "Draw only selected motion vectors"); ARG_DEF(NULL, "pp-dbg-mvs", 1, "Draw only selected motion vectors");
static const arg_def_t mfqe = ARG_DEF( static const arg_def_t mfqe =
NULL, "mfqe", 0, "Enable multiframe quality enhancement"); ARG_DEF(NULL, "mfqe", 0, "Enable multiframe quality enhancement");
static const arg_def_t *vp8_pp_args[] = { static const arg_def_t *vp8_pp_args[] = { &addnoise_level,
&addnoise_level, &deblock, &demacroblock_level, &pp_debug_info, &deblock,
&pp_disp_ref_frame, &pp_disp_mb_modes, &pp_disp_b_modes, &pp_disp_mvs, &mfqe, &demacroblock_level,
NULL &pp_debug_info,
}; &pp_disp_ref_frame,
&pp_disp_mb_modes,
&pp_disp_b_modes,
&pp_disp_mvs,
&mfqe,
NULL };
#endif #endif
#if CONFIG_LIBYUV #if CONFIG_LIBYUV
@ -139,42 +157,35 @@ static INLINE int libyuv_scale(vpx_image_t *src, vpx_image_t *dst,
#if CONFIG_VP9_HIGHBITDEPTH #if CONFIG_VP9_HIGHBITDEPTH
if (src->fmt == VPX_IMG_FMT_I42016) { if (src->fmt == VPX_IMG_FMT_I42016) {
assert(dst->fmt == VPX_IMG_FMT_I42016); assert(dst->fmt == VPX_IMG_FMT_I42016);
return I420Scale_16((uint16_t*)src->planes[VPX_PLANE_Y], return I420Scale_16(
src->stride[VPX_PLANE_Y]/2, (uint16_t *)src->planes[VPX_PLANE_Y], src->stride[VPX_PLANE_Y] / 2,
(uint16_t*)src->planes[VPX_PLANE_U], (uint16_t *)src->planes[VPX_PLANE_U], src->stride[VPX_PLANE_U] / 2,
src->stride[VPX_PLANE_U]/2, (uint16_t *)src->planes[VPX_PLANE_V], src->stride[VPX_PLANE_V] / 2,
(uint16_t*)src->planes[VPX_PLANE_V], src->d_w, src->d_h, (uint16_t *)dst->planes[VPX_PLANE_Y],
src->stride[VPX_PLANE_V]/2, dst->stride[VPX_PLANE_Y] / 2, (uint16_t *)dst->planes[VPX_PLANE_U],
src->d_w, src->d_h, dst->stride[VPX_PLANE_U] / 2, (uint16_t *)dst->planes[VPX_PLANE_V],
(uint16_t*)dst->planes[VPX_PLANE_Y], dst->stride[VPX_PLANE_V] / 2, dst->d_w, dst->d_h, mode);
dst->stride[VPX_PLANE_Y]/2,
(uint16_t*)dst->planes[VPX_PLANE_U],
dst->stride[VPX_PLANE_U]/2,
(uint16_t*)dst->planes[VPX_PLANE_V],
dst->stride[VPX_PLANE_V]/2,
dst->d_w, dst->d_h,
mode);
} }
#endif #endif
assert(src->fmt == VPX_IMG_FMT_I420); assert(src->fmt == VPX_IMG_FMT_I420);
assert(dst->fmt == VPX_IMG_FMT_I420); assert(dst->fmt == VPX_IMG_FMT_I420);
return I420Scale(src->planes[VPX_PLANE_Y], src->stride[VPX_PLANE_Y], return I420Scale(src->planes[VPX_PLANE_Y], src->stride[VPX_PLANE_Y],
src->planes[VPX_PLANE_U], src->stride[VPX_PLANE_U], src->planes[VPX_PLANE_U], src->stride[VPX_PLANE_U],
src->planes[VPX_PLANE_V], src->stride[VPX_PLANE_V], src->planes[VPX_PLANE_V], src->stride[VPX_PLANE_V], src->d_w,
src->d_w, src->d_h, src->d_h, dst->planes[VPX_PLANE_Y], dst->stride[VPX_PLANE_Y],
dst->planes[VPX_PLANE_Y], dst->stride[VPX_PLANE_Y],
dst->planes[VPX_PLANE_U], dst->stride[VPX_PLANE_U], dst->planes[VPX_PLANE_U], dst->stride[VPX_PLANE_U],
dst->planes[VPX_PLANE_V], dst->stride[VPX_PLANE_V], dst->planes[VPX_PLANE_V], dst->stride[VPX_PLANE_V], dst->d_w,
dst->d_w, dst->d_h, dst->d_h, mode);
mode);
} }
#endif #endif
void usage_exit(void) { void usage_exit(void) {
int i; int i;
fprintf(stderr, "Usage: %s <options> filename\n\n" fprintf(stderr,
"Options:\n", exec_name); "Usage: %s <options> filename\n\n"
"Options:\n",
exec_name);
arg_show_usage(stderr, all_args); arg_show_usage(stderr, all_args);
#if CONFIG_VP8_DECODER #if CONFIG_VP8_DECODER
fprintf(stderr, "\nVP8 Postprocessing Options:\n"); fprintf(stderr, "\nVP8 Postprocessing Options:\n");
@ -193,27 +204,25 @@ void usage_exit(void) {
"\n\t%%<n> - Frame number, zero padded to <n> places (1..9)" "\n\t%%<n> - Frame number, zero padded to <n> places (1..9)"
"\n\n Pattern arguments are only supported in conjunction " "\n\n Pattern arguments are only supported in conjunction "
"with the --yv12 and\n --i420 options. If the -o option is " "with the --yv12 and\n --i420 options. If the -o option is "
"not specified, the output will be\n directed to stdout.\n" "not specified, the output will be\n directed to stdout.\n");
);
fprintf(stderr, "\nIncluded decoders:\n\n"); fprintf(stderr, "\nIncluded decoders:\n\n");
for (i = 0; i < get_vpx_decoder_count(); ++i) { for (i = 0; i < get_vpx_decoder_count(); ++i) {
const VpxInterface *const decoder = get_vpx_decoder_by_index(i); const VpxInterface *const decoder = get_vpx_decoder_by_index(i);
fprintf(stderr, " %-6s - %s\n", fprintf(stderr, " %-6s - %s\n", decoder->name,
decoder->name, vpx_codec_iface_name(decoder->codec_interface())); vpx_codec_iface_name(decoder->codec_interface()));
} }
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
static int raw_read_frame(FILE *infile, uint8_t **buffer, static int raw_read_frame(FILE *infile, uint8_t **buffer, size_t *bytes_read,
size_t *bytes_read, size_t *buffer_size) { size_t *buffer_size) {
char raw_hdr[RAW_FRAME_HDR_SZ]; char raw_hdr[RAW_FRAME_HDR_SZ];
size_t frame_size = 0; size_t frame_size = 0;
if (fread(raw_hdr, RAW_FRAME_HDR_SZ, 1, infile) != 1) { if (fread(raw_hdr, RAW_FRAME_HDR_SZ, 1, infile) != 1) {
if (!feof(infile)) if (!feof(infile)) warn("Failed to read RAW frame size\n");
warn("Failed to read RAW frame size\n");
} else { } else {
const size_t kCorruptFrameThreshold = 256 * 1024 * 1024; const size_t kCorruptFrameThreshold = 256 * 1024 * 1024;
const size_t kFrameTooSmallThreshold = 256 * 1024; const size_t kFrameTooSmallThreshold = 256 * 1024;
@ -260,13 +269,12 @@ static int read_frame(struct VpxDecInputContext *input, uint8_t **buf,
return webm_read_frame(input->webm_ctx, buf, bytes_in_buffer); return webm_read_frame(input->webm_ctx, buf, bytes_in_buffer);
#endif #endif
case FILE_TYPE_RAW: case FILE_TYPE_RAW:
return raw_read_frame(input->vpx_input_ctx->file, return raw_read_frame(input->vpx_input_ctx->file, buf, bytes_in_buffer,
buf, bytes_in_buffer, buffer_size); buffer_size);
case FILE_TYPE_IVF: case FILE_TYPE_IVF:
return ivf_read_frame(input->vpx_input_ctx->file, return ivf_read_frame(input->vpx_input_ctx->file, buf, bytes_in_buffer,
buf, bytes_in_buffer, buffer_size); buffer_size);
default: default: return 1;
return 1;
} }
} }
@ -325,8 +333,8 @@ static int file_is_raw(struct VpxInputContext *input) {
if (mem_get_le32(buf) < 256 * 1024 * 1024) { if (mem_get_le32(buf) < 256 * 1024 * 1024) {
for (i = 0; i < get_vpx_decoder_count(); ++i) { for (i = 0; i < get_vpx_decoder_count(); ++i) {
const VpxInterface *const decoder = get_vpx_decoder_by_index(i); const VpxInterface *const decoder = get_vpx_decoder_by_index(i);
if (!vpx_codec_peek_stream_info(decoder->codec_interface(), if (!vpx_codec_peek_stream_info(decoder->codec_interface(), buf + 4,
buf + 4, 32 - 4, &si)) { 32 - 4, &si)) {
is_raw = 1; is_raw = 1;
input->fourcc = decoder->fourcc; input->fourcc = decoder->fourcc;
input->width = si.w; input->width = si.w;
@ -370,23 +378,19 @@ static int get_vp9_frame_buffer(void *cb_priv, size_t min_size,
int i; int i;
struct ExternalFrameBufferList *const ext_fb_list = struct ExternalFrameBufferList *const ext_fb_list =
(struct ExternalFrameBufferList *)cb_priv; (struct ExternalFrameBufferList *)cb_priv;
if (ext_fb_list == NULL) if (ext_fb_list == NULL) return -1;
return -1;
// Find a free frame buffer. // Find a free frame buffer.
for (i = 0; i < ext_fb_list->num_external_frame_buffers; ++i) { for (i = 0; i < ext_fb_list->num_external_frame_buffers; ++i) {
if (!ext_fb_list->ext_fb[i].in_use) if (!ext_fb_list->ext_fb[i].in_use) break;
break;
} }
if (i == ext_fb_list->num_external_frame_buffers) if (i == ext_fb_list->num_external_frame_buffers) return -1;
return -1;
if (ext_fb_list->ext_fb[i].size < min_size) { if (ext_fb_list->ext_fb[i].size < min_size) {
free(ext_fb_list->ext_fb[i].data); free(ext_fb_list->ext_fb[i].data);
ext_fb_list->ext_fb[i].data = (uint8_t *)calloc(min_size, sizeof(uint8_t)); ext_fb_list->ext_fb[i].data = (uint8_t *)calloc(min_size, sizeof(uint8_t));
if (!ext_fb_list->ext_fb[i].data) if (!ext_fb_list->ext_fb[i].data) return -1;
return -1;
ext_fb_list->ext_fb[i].size = min_size; ext_fb_list->ext_fb[i].size = min_size;
} }
@ -427,47 +431,22 @@ static void generate_filename(const char *pattern, char *out, size_t q_len,
/* parse the pattern */ /* parse the pattern */
q[q_len - 1] = '\0'; q[q_len - 1] = '\0';
switch (p[1]) { switch (p[1]) {
case 'w': case 'w': snprintf(q, q_len - 1, "%d", d_w); break;
snprintf(q, q_len - 1, "%d", d_w); case 'h': snprintf(q, q_len - 1, "%d", d_h); break;
break; case '1': snprintf(q, q_len - 1, "%d", frame_in); break;
case 'h': case '2': snprintf(q, q_len - 1, "%02d", frame_in); break;
snprintf(q, q_len - 1, "%d", d_h); case '3': snprintf(q, q_len - 1, "%03d", frame_in); break;
break; case '4': snprintf(q, q_len - 1, "%04d", frame_in); break;
case '1': case '5': snprintf(q, q_len - 1, "%05d", frame_in); break;
snprintf(q, q_len - 1, "%d", frame_in); case '6': snprintf(q, q_len - 1, "%06d", frame_in); break;
break; case '7': snprintf(q, q_len - 1, "%07d", frame_in); break;
case '2': case '8': snprintf(q, q_len - 1, "%08d", frame_in); break;
snprintf(q, q_len - 1, "%02d", frame_in); case '9': snprintf(q, q_len - 1, "%09d", frame_in); break;
break; default: die("Unrecognized pattern %%%c\n", p[1]); break;
case '3':
snprintf(q, q_len - 1, "%03d", frame_in);
break;
case '4':
snprintf(q, q_len - 1, "%04d", frame_in);
break;
case '5':
snprintf(q, q_len - 1, "%05d", frame_in);
break;
case '6':
snprintf(q, q_len - 1, "%06d", frame_in);
break;
case '7':
snprintf(q, q_len - 1, "%07d", frame_in);
break;
case '8':
snprintf(q, q_len - 1, "%08d", frame_in);
break;
case '9':
snprintf(q, q_len - 1, "%09d", frame_in);
break;
default:
die("Unrecognized pattern %%%c\n", p[1]);
break;
} }
pat_len = strlen(q); pat_len = strlen(q);
if (pat_len >= q_len - 1) if (pat_len >= q_len - 1) die("Output filename too long.\n");
die("Output filename too long.\n");
q += pat_len; q += pat_len;
p += 2; p += 2;
q_len -= pat_len; q_len -= pat_len;
@ -480,8 +459,7 @@ static void generate_filename(const char *pattern, char *out, size_t q_len,
else else
copy_len = next_pat - p; copy_len = next_pat - p;
if (copy_len >= q_len - 1) if (copy_len >= q_len - 1) die("Output filename too long.\n");
die("Output filename too long.\n");
memcpy(q, p, copy_len); memcpy(q, p, copy_len);
q[copy_len] = '\0'; q[copy_len] = '\0';
@ -499,8 +477,7 @@ static int is_single_file(const char *outfile_pattern) {
p = strchr(p, '%'); p = strchr(p, '%');
if (p && p[1] >= '1' && p[1] <= '9') if (p && p[1] >= '1' && p[1] <= '9')
return 0; // pattern contains sequence number, so it's not unique return 0; // pattern contains sequence number, so it's not unique
if (p) if (p) p++;
p++;
} while (p); } while (p);
return 1; return 1;
@ -509,8 +486,7 @@ static int is_single_file(const char *outfile_pattern) {
static void print_md5(unsigned char digest[16], const char *filename) { static void print_md5(unsigned char digest[16], const char *filename) {
int i; int i;
for (i = 0; i < 16; ++i) for (i = 0; i < 16; ++i) printf("%02x", digest[i]);
printf("%02x", digest[i]);
printf(" %s\n", filename); printf(" %s\n", filename);
} }
@ -520,8 +496,7 @@ static FILE *open_outfile(const char *name) {
return stdout; return stdout;
} else { } else {
FILE *file = fopen(name, "wb"); FILE *file = fopen(name, "wb");
if (!file) if (!file) fatal("Failed to open output file '%s'", name);
fatal("Failed to open output file '%s'", name);
return file; return file;
} }
} }
@ -530,8 +505,7 @@ static FILE *open_outfile(const char *name) {
static int img_shifted_realloc_required(const vpx_image_t *img, static int img_shifted_realloc_required(const vpx_image_t *img,
const vpx_image_t *shifted, const vpx_image_t *shifted,
vpx_img_fmt_t required_fmt) { vpx_img_fmt_t required_fmt) {
return img->d_w != shifted->d_w || return img->d_w != shifted->d_w || img->d_h != shifted->d_h ||
img->d_h != shifted->d_h ||
required_fmt != shifted->fmt; required_fmt != shifted->fmt;
} }
#endif #endif
@ -679,8 +653,7 @@ static int main_loop(int argc, const char **argv_) {
postproc = 1; postproc = 1;
vp8_pp_cfg.post_proc_flag &= ~0x7; vp8_pp_cfg.post_proc_flag &= ~0x7;
if (level) if (level) vp8_pp_cfg.post_proc_flag |= level;
vp8_pp_cfg.post_proc_flag |= level;
} else if (arg_match(&arg, &pp_disp_ref_frame, argi)) { } else if (arg_match(&arg, &pp_disp_ref_frame, argi)) {
unsigned int flags = arg_parse_int(&arg); unsigned int flags = arg_parse_int(&arg);
if (flags) { if (flags) {
@ -771,7 +744,8 @@ static int main_loop(int argc, const char **argv_) {
if (use_y4m && !noblit) { if (use_y4m && !noblit) {
if (!single_file) { if (!single_file) {
fprintf(stderr, "YUV4MPEG2 not supported with output patterns," fprintf(stderr,
"YUV4MPEG2 not supported with output patterns,"
" try --i420 or --yv12 or --rawvideo.\n"); " try --i420 or --yv12 or --rawvideo.\n");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
@ -779,7 +753,8 @@ static int main_loop(int argc, const char **argv_) {
#if CONFIG_WEBM_IO #if CONFIG_WEBM_IO
if (vpx_input_ctx.file_type == FILE_TYPE_WEBM) { if (vpx_input_ctx.file_type == FILE_TYPE_WEBM) {
if (webm_guess_framerate(input.webm_ctx, input.vpx_input_ctx)) { if (webm_guess_framerate(input.webm_ctx, input.vpx_input_ctx)) {
fprintf(stderr, "Failed to guess framerate -- error parsing " fprintf(stderr,
"Failed to guess framerate -- error parsing "
"webm file?\n"); "webm file?\n");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
@ -793,69 +768,63 @@ static int main_loop(int argc, const char **argv_) {
else else
interface = fourcc_interface; interface = fourcc_interface;
if (!interface) if (!interface) interface = get_vpx_decoder_by_index(0);
interface = get_vpx_decoder_by_index(0);
dec_flags = (postproc ? VPX_CODEC_USE_POSTPROC : 0) | dec_flags = (postproc ? VPX_CODEC_USE_POSTPROC : 0) |
(ec_enabled ? VPX_CODEC_USE_ERROR_CONCEALMENT : 0) | (ec_enabled ? VPX_CODEC_USE_ERROR_CONCEALMENT : 0) |
(frame_parallel ? VPX_CODEC_USE_FRAME_THREADING : 0); (frame_parallel ? VPX_CODEC_USE_FRAME_THREADING : 0);
if (vpx_codec_dec_init(&decoder, interface->codec_interface(), if (vpx_codec_dec_init(&decoder, interface->codec_interface(), &cfg,
&cfg, dec_flags)) { dec_flags)) {
fprintf(stderr, "Failed to initialize decoder: %s\n", fprintf(stderr, "Failed to initialize decoder: %s\n",
vpx_codec_error(&decoder)); vpx_codec_error(&decoder));
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if (!quiet) if (!quiet) fprintf(stderr, "%s\n", decoder.name);
fprintf(stderr, "%s\n", decoder.name);
#if CONFIG_VP8_DECODER #if CONFIG_VP8_DECODER
if (vp8_pp_cfg.post_proc_flag if (vp8_pp_cfg.post_proc_flag &&
&& vpx_codec_control(&decoder, VP8_SET_POSTPROC, &vp8_pp_cfg)) { vpx_codec_control(&decoder, VP8_SET_POSTPROC, &vp8_pp_cfg)) {
fprintf(stderr, "Failed to configure postproc: %s\n", fprintf(stderr, "Failed to configure postproc: %s\n",
vpx_codec_error(&decoder)); vpx_codec_error(&decoder));
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if (vp8_dbg_color_ref_frame if (vp8_dbg_color_ref_frame &&
&& vpx_codec_control(&decoder, VP8_SET_DBG_COLOR_REF_FRAME, vpx_codec_control(&decoder, VP8_SET_DBG_COLOR_REF_FRAME,
vp8_dbg_color_ref_frame)) { vp8_dbg_color_ref_frame)) {
fprintf(stderr, "Failed to configure reference block visualizer: %s\n", fprintf(stderr, "Failed to configure reference block visualizer: %s\n",
vpx_codec_error(&decoder)); vpx_codec_error(&decoder));
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if (vp8_dbg_color_mb_modes if (vp8_dbg_color_mb_modes &&
&& vpx_codec_control(&decoder, VP8_SET_DBG_COLOR_MB_MODES, vpx_codec_control(&decoder, VP8_SET_DBG_COLOR_MB_MODES,
vp8_dbg_color_mb_modes)) { vp8_dbg_color_mb_modes)) {
fprintf(stderr, "Failed to configure macro block visualizer: %s\n", fprintf(stderr, "Failed to configure macro block visualizer: %s\n",
vpx_codec_error(&decoder)); vpx_codec_error(&decoder));
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if (vp8_dbg_color_b_modes if (vp8_dbg_color_b_modes &&
&& vpx_codec_control(&decoder, VP8_SET_DBG_COLOR_B_MODES, vpx_codec_control(&decoder, VP8_SET_DBG_COLOR_B_MODES,
vp8_dbg_color_b_modes)) { vp8_dbg_color_b_modes)) {
fprintf(stderr, "Failed to configure block visualizer: %s\n", fprintf(stderr, "Failed to configure block visualizer: %s\n",
vpx_codec_error(&decoder)); vpx_codec_error(&decoder));
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if (vp8_dbg_display_mv if (vp8_dbg_display_mv &&
&& vpx_codec_control(&decoder, VP8_SET_DBG_DISPLAY_MV, vpx_codec_control(&decoder, VP8_SET_DBG_DISPLAY_MV, vp8_dbg_display_mv)) {
vp8_dbg_display_mv)) {
fprintf(stderr, "Failed to configure motion vector visualizer: %s\n", fprintf(stderr, "Failed to configure motion vector visualizer: %s\n",
vpx_codec_error(&decoder)); vpx_codec_error(&decoder));
return EXIT_FAILURE; return EXIT_FAILURE;
} }
#endif #endif
if (arg_skip) fprintf(stderr, "Skipping first %d frames.\n", arg_skip);
if (arg_skip)
fprintf(stderr, "Skipping first %d frames.\n", arg_skip);
while (arg_skip) { while (arg_skip) {
if (read_frame(&input, &buf, &bytes_in_buffer, &buffer_size)) if (read_frame(&input, &buf, &bytes_in_buffer, &buffer_size)) break;
break;
arg_skip--; arg_skip--;
} }
@ -863,8 +832,8 @@ static int main_loop(int argc, const char **argv_) {
ext_fb_list.num_external_frame_buffers = num_external_frame_buffers; ext_fb_list.num_external_frame_buffers = num_external_frame_buffers;
ext_fb_list.ext_fb = (struct ExternalFrameBuffer *)calloc( ext_fb_list.ext_fb = (struct ExternalFrameBuffer *)calloc(
num_external_frame_buffers, sizeof(*ext_fb_list.ext_fb)); num_external_frame_buffers, sizeof(*ext_fb_list.ext_fb));
if (vpx_codec_set_frame_buffer_functions( if (vpx_codec_set_frame_buffer_functions(&decoder, get_vp9_frame_buffer,
&decoder, get_vp9_frame_buffer, release_vp9_frame_buffer, release_vp9_frame_buffer,
&ext_fb_list)) { &ext_fb_list)) {
fprintf(stderr, "Failed to configure external frame buffers: %s\n", fprintf(stderr, "Failed to configure external frame buffers: %s\n",
vpx_codec_error(&decoder)); vpx_codec_error(&decoder));
@ -890,16 +859,14 @@ static int main_loop(int argc, const char **argv_) {
vpx_usec_timer_start(&timer); vpx_usec_timer_start(&timer);
if (vpx_codec_decode(&decoder, buf, (unsigned int)bytes_in_buffer, if (vpx_codec_decode(&decoder, buf, (unsigned int)bytes_in_buffer, NULL,
NULL, 0)) { 0)) {
const char *detail = vpx_codec_error_detail(&decoder); const char *detail = vpx_codec_error_detail(&decoder);
warn("Failed to decode frame %d: %s", warn("Failed to decode frame %d: %s", frame_in,
frame_in, vpx_codec_error(&decoder)); vpx_codec_error(&decoder));
if (detail) if (detail) warn("Additional information: %s", detail);
warn("Additional information: %s", detail); if (!keep_going) goto fail;
if (!keep_going)
goto fail;
} }
vpx_usec_timer_mark(&timer); vpx_usec_timer_mark(&timer);
@ -932,13 +899,11 @@ static int main_loop(int argc, const char **argv_) {
if (!frame_parallel && if (!frame_parallel &&
vpx_codec_control(&decoder, VP8D_GET_FRAME_CORRUPTED, &corrupted)) { vpx_codec_control(&decoder, VP8D_GET_FRAME_CORRUPTED, &corrupted)) {
warn("Failed VP8_GET_FRAME_CORRUPTED: %s", vpx_codec_error(&decoder)); warn("Failed VP8_GET_FRAME_CORRUPTED: %s", vpx_codec_error(&decoder));
if (!keep_going) if (!keep_going) goto fail;
goto fail;
} }
frames_corrupted += corrupted; frames_corrupted += corrupted;
if (progress) if (progress) show_progress(frame_in, frame_out, dx_time);
show_progress(frame_in, frame_out, dx_time);
if (!noblit && img) { if (!noblit && img) {
const int PLANES_YUV[] = { VPX_PLANE_Y, VPX_PLANE_U, VPX_PLANE_V }; const int PLANES_YUV[] = { VPX_PLANE_Y, VPX_PLANE_U, VPX_PLANE_V };
@ -966,8 +931,8 @@ static int main_loop(int argc, const char **argv_) {
render_height = render_size[1]; render_height = render_size[1];
} }
} }
scaled_img = vpx_img_alloc(NULL, img->fmt, render_width, scaled_img =
render_height, 16); vpx_img_alloc(NULL, img->fmt, render_width, render_height, 16);
scaled_img->bit_depth = img->bit_depth; scaled_img->bit_depth = img->bit_depth;
} }
@ -976,7 +941,8 @@ static int main_loop(int argc, const char **argv_) {
libyuv_scale(img, scaled_img, kFilterBox); libyuv_scale(img, scaled_img, kFilterBox);
img = scaled_img; img = scaled_img;
#else #else
fprintf(stderr, "Failed to scale output frame: %s.\n" fprintf(stderr,
"Failed to scale output frame: %s.\n"
"Scaling is disabled in this configuration. " "Scaling is disabled in this configuration. "
"To enable scaling, configure with --enable-libyuv\n", "To enable scaling, configure with --enable-libyuv\n",
vpx_codec_error(&decoder)); vpx_codec_error(&decoder));
@ -991,22 +957,22 @@ static int main_loop(int argc, const char **argv_) {
} }
// Shift up or down if necessary // Shift up or down if necessary
if (output_bit_depth != 0 && output_bit_depth != img->bit_depth) { if (output_bit_depth != 0 && output_bit_depth != img->bit_depth) {
const vpx_img_fmt_t shifted_fmt = output_bit_depth == 8 ? const vpx_img_fmt_t shifted_fmt =
img->fmt ^ (img->fmt & VPX_IMG_FMT_HIGHBITDEPTH) : output_bit_depth == 8
img->fmt | VPX_IMG_FMT_HIGHBITDEPTH; ? img->fmt ^ (img->fmt & VPX_IMG_FMT_HIGHBITDEPTH)
: img->fmt | VPX_IMG_FMT_HIGHBITDEPTH;
if (img_shifted && if (img_shifted &&
img_shifted_realloc_required(img, img_shifted, shifted_fmt)) { img_shifted_realloc_required(img, img_shifted, shifted_fmt)) {
vpx_img_free(img_shifted); vpx_img_free(img_shifted);
img_shifted = NULL; img_shifted = NULL;
} }
if (!img_shifted) { if (!img_shifted) {
img_shifted = vpx_img_alloc(NULL, shifted_fmt, img_shifted =
img->d_w, img->d_h, 16); vpx_img_alloc(NULL, shifted_fmt, img->d_w, img->d_h, 16);
img_shifted->bit_depth = output_bit_depth; img_shifted->bit_depth = output_bit_depth;
} }
if (output_bit_depth > img->bit_depth) { if (output_bit_depth > img->bit_depth) {
vpx_img_upshift(img_shifted, img, vpx_img_upshift(img_shifted, img, output_bit_depth - img->bit_depth);
output_bit_depth - img->bit_depth);
} else { } else {
vpx_img_downshift(img_shifted, img, vpx_img_downshift(img_shifted, img,
img->bit_depth - output_bit_depth); img->bit_depth - output_bit_depth);
@ -1025,11 +991,9 @@ static int main_loop(int argc, const char **argv_) {
} }
if (frame_out == 1) { if (frame_out == 1) {
// Y4M file header // Y4M file header
len = y4m_write_file_header(buf, sizeof(buf), len = y4m_write_file_header(
vpx_input_ctx.width, buf, sizeof(buf), vpx_input_ctx.width, vpx_input_ctx.height,
vpx_input_ctx.height, &vpx_input_ctx.framerate, img->fmt, img->bit_depth);
&vpx_input_ctx.framerate,
img->fmt, img->bit_depth);
if (do_md5) { if (do_md5) {
MD5Update(&md5_ctx, (md5byte *)buf, (unsigned int)len); MD5Update(&md5_ctx, (md5byte *)buf, (unsigned int)len);
} else { } else {
@ -1057,7 +1021,8 @@ static int main_loop(int argc, const char **argv_) {
} }
if (opt_yv12) { if (opt_yv12) {
if ((img->fmt != VPX_IMG_FMT_I420 && if ((img->fmt != VPX_IMG_FMT_I420 &&
img->fmt != VPX_IMG_FMT_YV12) || img->bit_depth != 8) { img->fmt != VPX_IMG_FMT_YV12) ||
img->bit_depth != 8) {
fprintf(stderr, "Cannot produce yv12 output for bit-stream.\n"); fprintf(stderr, "Cannot produce yv12 output for bit-stream.\n");
goto fail; goto fail;
} }
@ -1071,8 +1036,8 @@ static int main_loop(int argc, const char **argv_) {
write_image_file(img, planes, outfile); write_image_file(img, planes, outfile);
} }
} else { } else {
generate_filename(outfile_pattern, outfile_name, PATH_MAX, generate_filename(outfile_pattern, outfile_name, PATH_MAX, img->d_w,
img->d_w, img->d_h, frame_in); img->d_h, frame_in);
if (do_md5) { if (do_md5) {
MD5Init(&md5_ctx); MD5Init(&md5_ctx);
update_image_md5(img, planes, &md5_ctx); update_image_md5(img, planes, &md5_ctx);
@ -1117,8 +1082,7 @@ fail:
webm_free(input.webm_ctx); webm_free(input.webm_ctx);
#endif #endif
if (input.vpx_input_ctx->file_type != FILE_TYPE_WEBM) if (input.vpx_input_ctx->file_type != FILE_TYPE_WEBM) free(buf);
free(buf);
if (scaled_img) vpx_img_free(scaled_img); if (scaled_img) vpx_img_free(scaled_img);
#if CONFIG_VP9_HIGHBITDEPTH #if CONFIG_VP9_HIGHBITDEPTH
@ -1153,7 +1117,6 @@ int main(int argc, const char **argv_) {
} }
} }
free(argv); free(argv);
for (i = 0; !error && i < loops; i++) for (i = 0; !error && i < loops; i++) error = main_loop(argc, argv_);
error = main_loop(argc, argv_);
return error; return error;
} }

865
vpxenc.c

File diff suppressed because it is too large Load Diff

View File

@ -30,8 +30,7 @@ int stats_open_file(stats_io_t *stats, const char *fpf, int pass) {
stats->file = fopen(fpf, "rb"); stats->file = fopen(fpf, "rb");
if (stats->file == NULL) if (stats->file == NULL) fatal("First-pass stats file does not exist!");
fatal("First-pass stats file does not exist!");
if (fseek(stats->file, 0, SEEK_END)) if (fseek(stats->file, 0, SEEK_END))
fatal("First-pass stats file must be seekable!"); fatal("First-pass stats file must be seekable!");
@ -76,8 +75,7 @@ void stats_close(stats_io_t *stats, int last_pass) {
fclose(stats->file); fclose(stats->file);
stats->file = NULL; stats->file = NULL;
} else { } else {
if (stats->pass == last_pass) if (stats->pass == last_pass) free(stats->buf.buf);
free(stats->buf.buf);
} }
} }
@ -104,6 +102,4 @@ void stats_write(stats_io_t *stats, const void *pkt, size_t len) {
} }
} }
vpx_fixed_buf_t stats_get(stats_io_t *stats) { vpx_fixed_buf_t stats_get(stats_io_t *stats) { return stats->buf; }
return stats->buf;
}

View File

@ -47,8 +47,7 @@ static void add_warning(const char *warning_string,
new_node->warning_string = warning_string; new_node->warning_string = warning_string;
new_node->next_warning = NULL; new_node->next_warning = NULL;
while (*node != NULL) while (*node != NULL) node = &(*node)->next_warning;
node = &(*node)->next_warning;
*node = new_node; *node = new_node;
} }
@ -78,9 +77,7 @@ static void check_quantizer(int min_q, int max_q,
} }
static void check_lag_in_frames_realtime_deadline( static void check_lag_in_frames_realtime_deadline(
int lag_in_frames, int lag_in_frames, int deadline, int rc_end_usage,
int deadline,
int rc_end_usage,
struct WarningList *warning_list) { struct WarningList *warning_list) {
if (deadline == VPX_DL_REALTIME && lag_in_frames != 0 && rc_end_usage == 1) if (deadline == VPX_DL_REALTIME && lag_in_frames != 0 && rc_end_usage == 1)
add_warning(lag_in_frames_with_realtime, warning_list); add_warning(lag_in_frames_with_realtime, warning_list);
@ -94,24 +91,19 @@ void check_encoder_config(int disable_prompt,
struct WarningList warning_list = { 0 }; struct WarningList warning_list = { 0 };
check_quantizer(stream_config->rc_min_quantizer, check_quantizer(stream_config->rc_min_quantizer,
stream_config->rc_max_quantizer, stream_config->rc_max_quantizer, &warning_list);
&warning_list); check_lag_in_frames_realtime_deadline(
check_lag_in_frames_realtime_deadline(stream_config->g_lag_in_frames, stream_config->g_lag_in_frames, global_config->deadline,
global_config->deadline, stream_config->rc_end_usage, &warning_list);
stream_config->rc_end_usage,
&warning_list);
/* Count and print warnings. */ /* Count and print warnings. */
for (warning = warning_list.warning_node; for (warning = warning_list.warning_node; warning != NULL;
warning != NULL; warning = warning->next_warning, ++num_warnings) {
warning = warning->next_warning,
++num_warnings) {
warn(warning->warning_string); warn(warning->warning_string);
} }
free_warning_list(&warning_list); free_warning_list(&warning_list);
if (num_warnings) { if (num_warnings) {
if (!disable_prompt && !continue_prompt(num_warnings)) if (!disable_prompt && !continue_prompt(num_warnings)) exit(EXIT_FAILURE);
exit(EXIT_FAILURE);
} }
} }

View File

@ -118,8 +118,7 @@ int file_is_webm(struct WebmInputContext *webm_ctx,
return 1; return 1;
} }
int webm_read_frame(struct WebmInputContext *webm_ctx, int webm_read_frame(struct WebmInputContext *webm_ctx, uint8_t **buffer,
uint8_t **buffer,
size_t *buffer_size) { size_t *buffer_size) {
// This check is needed for frame parallel decoding, in which case this // This check is needed for frame parallel decoding, in which case this
// function could be called even after it has reached end of input stream. // function could be called even after it has reached end of input stream.
@ -221,6 +220,4 @@ int webm_guess_framerate(struct WebmInputContext *webm_ctx,
return 0; return 0;
} }
void webm_free(struct WebmInputContext *webm_ctx) { void webm_free(struct WebmInputContext *webm_ctx) { reset(webm_ctx); }
reset(webm_ctx);
}

View File

@ -52,8 +52,7 @@ int file_is_webm(struct WebmInputContext *webm_ctx,
// 0 - Success // 0 - Success
// 1 - End of Stream // 1 - End of Stream
// -1 - Error // -1 - Error
int webm_read_frame(struct WebmInputContext *webm_ctx, int webm_read_frame(struct WebmInputContext *webm_ctx, uint8_t **buffer,
uint8_t **buffer,
size_t *buffer_size); size_t *buffer_size);
// Guesses the frame rate of the input file based on the container timestamps. // Guesses the frame rate of the input file based on the container timestamps.

View File

@ -23,8 +23,7 @@ const int kVideoTrackNumber = 1;
void write_webm_file_header(struct WebmOutputContext *webm_ctx, void write_webm_file_header(struct WebmOutputContext *webm_ctx,
const vpx_codec_enc_cfg_t *cfg, const vpx_codec_enc_cfg_t *cfg,
const struct vpx_rational *fps, const struct vpx_rational *fps,
stereo_format_t stereo_fmt, stereo_format_t stereo_fmt, unsigned int fourcc,
unsigned int fourcc,
const struct VpxRational *par) { const struct VpxRational *par) {
mkvmuxer::MkvWriter *const writer = new mkvmuxer::MkvWriter(webm_ctx->stream); mkvmuxer::MkvWriter *const writer = new mkvmuxer::MkvWriter(webm_ctx->stream);
mkvmuxer::Segment *const segment = new mkvmuxer::Segment(); mkvmuxer::Segment *const segment = new mkvmuxer::Segment();
@ -43,29 +42,22 @@ void write_webm_file_header(struct WebmOutputContext *webm_ctx,
const uint64_t video_track_id = const uint64_t video_track_id =
segment->AddVideoTrack(static_cast<int>(cfg->g_w), segment->AddVideoTrack(static_cast<int>(cfg->g_w),
static_cast<int>(cfg->g_h), static_cast<int>(cfg->g_h), kVideoTrackNumber);
kVideoTrackNumber); mkvmuxer::VideoTrack *const video_track = static_cast<mkvmuxer::VideoTrack *>(
mkvmuxer::VideoTrack* const video_track =
static_cast<mkvmuxer::VideoTrack*>(
segment->GetTrackByNumber(video_track_id)); segment->GetTrackByNumber(video_track_id));
video_track->SetStereoMode(stereo_fmt); video_track->SetStereoMode(stereo_fmt);
const char *codec_id; const char *codec_id;
switch (fourcc) { switch (fourcc) {
case VP8_FOURCC: case VP8_FOURCC: codec_id = "V_VP8"; break;
codec_id = "V_VP8";
break;
case VP9_FOURCC: case VP9_FOURCC:
default: default: codec_id = "V_VP9"; break;
codec_id = "V_VP9";
break;
} }
video_track->set_codec_id(codec_id); video_track->set_codec_id(codec_id);
if (par->numerator > 1 || par->denominator > 1) { if (par->numerator > 1 || par->denominator > 1) {
// TODO(fgalligan): Add support of DisplayUnit, Display Aspect Ratio type // TODO(fgalligan): Add support of DisplayUnit, Display Aspect Ratio type
// to WebM format. // to WebM format.
const uint64_t display_width = const uint64_t display_width = static_cast<uint64_t>(
static_cast<uint64_t>(((cfg->g_w * par->numerator * 1.0) / ((cfg->g_w * par->numerator * 1.0) / par->denominator) + .5);
par->denominator) + .5);
video_track->set_display_width(display_width); video_track->set_display_width(display_width);
video_track->set_display_height(cfg->g_h); video_track->set_display_height(cfg->g_h);
} }
@ -81,16 +73,13 @@ void write_webm_block(struct WebmOutputContext *webm_ctx,
const vpx_codec_cx_pkt_t *pkt) { const vpx_codec_cx_pkt_t *pkt) {
mkvmuxer::Segment *const segment = mkvmuxer::Segment *const segment =
reinterpret_cast<mkvmuxer::Segment *>(webm_ctx->segment); reinterpret_cast<mkvmuxer::Segment *>(webm_ctx->segment);
int64_t pts_ns = pkt->data.frame.pts * 1000000000ll * int64_t pts_ns = pkt->data.frame.pts * 1000000000ll * cfg->g_timebase.num /
cfg->g_timebase.num / cfg->g_timebase.den; cfg->g_timebase.den;
if (pts_ns <= webm_ctx->last_pts_ns) if (pts_ns <= webm_ctx->last_pts_ns) pts_ns = webm_ctx->last_pts_ns + 1000000;
pts_ns = webm_ctx->last_pts_ns + 1000000;
webm_ctx->last_pts_ns = pts_ns; webm_ctx->last_pts_ns = pts_ns;
segment->AddFrame(static_cast<uint8_t *>(pkt->data.frame.buf), segment->AddFrame(static_cast<uint8_t *>(pkt->data.frame.buf),
pkt->data.frame.sz, pkt->data.frame.sz, kVideoTrackNumber, pts_ns,
kVideoTrackNumber,
pts_ns,
pkt->data.frame.flags & VPX_FRAME_IS_KEY); pkt->data.frame.flags & VPX_FRAME_IS_KEY);
} }

View File

@ -40,8 +40,7 @@ typedef enum stereo_format {
void write_webm_file_header(struct WebmOutputContext *webm_ctx, void write_webm_file_header(struct WebmOutputContext *webm_ctx,
const vpx_codec_enc_cfg_t *cfg, const vpx_codec_enc_cfg_t *cfg,
const struct vpx_rational *fps, const struct vpx_rational *fps,
stereo_format_t stereo_fmt, stereo_format_t stereo_fmt, unsigned int fourcc,
unsigned int fourcc,
const struct VpxRational *par); const struct VpxRational *par);
void write_webm_block(struct WebmOutputContext *webm_ctx, void write_webm_block(struct WebmOutputContext *webm_ctx,

View File

@ -17,39 +17,43 @@ int y4m_write_file_header(char *buf, size_t len, int width, int height,
const char *color; const char *color;
switch (bit_depth) { switch (bit_depth) {
case 8: case 8:
color = fmt == VPX_IMG_FMT_444A ? "C444alpha\n" : color = fmt == VPX_IMG_FMT_444A
fmt == VPX_IMG_FMT_I444 ? "C444\n" : ? "C444alpha\n"
fmt == VPX_IMG_FMT_I422 ? "C422\n" : : fmt == VPX_IMG_FMT_I444 ? "C444\n" : fmt == VPX_IMG_FMT_I422
"C420jpeg\n"; ? "C422\n"
: "C420jpeg\n";
break; break;
case 9: case 9:
color = fmt == VPX_IMG_FMT_I44416 ? "C444p9 XYSCSS=444P9\n" : color = fmt == VPX_IMG_FMT_I44416
fmt == VPX_IMG_FMT_I42216 ? "C422p9 XYSCSS=422P9\n" : ? "C444p9 XYSCSS=444P9\n"
"C420p9 XYSCSS=420P9\n"; : fmt == VPX_IMG_FMT_I42216 ? "C422p9 XYSCSS=422P9\n"
: "C420p9 XYSCSS=420P9\n";
break; break;
case 10: case 10:
color = fmt == VPX_IMG_FMT_I44416 ? "C444p10 XYSCSS=444P10\n" : color = fmt == VPX_IMG_FMT_I44416
fmt == VPX_IMG_FMT_I42216 ? "C422p10 XYSCSS=422P10\n" : ? "C444p10 XYSCSS=444P10\n"
"C420p10 XYSCSS=420P10\n"; : fmt == VPX_IMG_FMT_I42216 ? "C422p10 XYSCSS=422P10\n"
: "C420p10 XYSCSS=420P10\n";
break; break;
case 12: case 12:
color = fmt == VPX_IMG_FMT_I44416 ? "C444p12 XYSCSS=444P12\n" : color = fmt == VPX_IMG_FMT_I44416
fmt == VPX_IMG_FMT_I42216 ? "C422p12 XYSCSS=422P12\n" : ? "C444p12 XYSCSS=444P12\n"
"C420p12 XYSCSS=420P12\n"; : fmt == VPX_IMG_FMT_I42216 ? "C422p12 XYSCSS=422P12\n"
: "C420p12 XYSCSS=420P12\n";
break; break;
case 14: case 14:
color = fmt == VPX_IMG_FMT_I44416 ? "C444p14 XYSCSS=444P14\n" : color = fmt == VPX_IMG_FMT_I44416
fmt == VPX_IMG_FMT_I42216 ? "C422p14 XYSCSS=422P14\n" : ? "C444p14 XYSCSS=444P14\n"
"C420p14 XYSCSS=420P14\n"; : fmt == VPX_IMG_FMT_I42216 ? "C422p14 XYSCSS=422P14\n"
: "C420p14 XYSCSS=420P14\n";
break; break;
case 16: case 16:
color = fmt == VPX_IMG_FMT_I44416 ? "C444p16 XYSCSS=444P16\n" : color = fmt == VPX_IMG_FMT_I44416
fmt == VPX_IMG_FMT_I42216 ? "C422p16 XYSCSS=422P16\n" : ? "C444p16 XYSCSS=444P16\n"
"C420p16 XYSCSS=420P16\n"; : fmt == VPX_IMG_FMT_I42216 ? "C422p16 XYSCSS=422P16\n"
: "C420p16 XYSCSS=420P16\n";
break; break;
default: default: color = NULL; assert(0);
color = NULL;
assert(0);
} }
return snprintf(buf, len, "YUV4MPEG2 W%u H%u F%u:%u I%c %s", width, height, return snprintf(buf, len, "YUV4MPEG2 W%u H%u F%u:%u I%c %s", width, height,
framerate->numerator, framerate->denominator, 'p', color); framerate->numerator, framerate->denominator, 'p', color);

View File

@ -41,10 +41,11 @@ static int file_read(void *buf, size_t size, FILE *file) {
} while (!feof(file) && len < size && ++retry_count < kMaxRetries); } while (!feof(file) && len < size && ++retry_count < kMaxRetries);
if (!feof(file) && len != size) { if (!feof(file) && len != size) {
fprintf(stderr, "Error reading file: %u of %u bytes read," fprintf(stderr,
"Error reading file: %u of %u bytes read,"
" error: %d, retries: %d, %d: %s\n", " error: %d, retries: %d, %d: %s\n",
(uint32_t)len, (uint32_t)size, file_error, retry_count, (uint32_t)len, (uint32_t)size, file_error, retry_count, errno,
errno, strerror(errno)); strerror(errno));
} }
return len == size; return len == size;
} }
@ -65,45 +66,40 @@ static int y4m_parse_tags(y4m_input *_y4m, char *_tags) {
/*If that's all we have, stop.*/ /*If that's all we have, stop.*/
if (p[0] == '\0') break; if (p[0] == '\0') break;
/*Find the end of this tag.*/ /*Find the end of this tag.*/
for (q = p + 1; *q != '\0' && *q != ' '; q++); for (q = p + 1; *q != '\0' && *q != ' '; q++)
;
/*Process the tag.*/ /*Process the tag.*/
switch (p[0]) { switch (p[0]) {
case 'W': { case 'W': {
if (sscanf(p + 1, "%d", &_y4m->pic_w) != 1) return -1; if (sscanf(p + 1, "%d", &_y4m->pic_w) != 1) return -1;
got_w = 1; got_w = 1;
} } break;
break;
case 'H': { case 'H': {
if (sscanf(p + 1, "%d", &_y4m->pic_h) != 1) return -1; if (sscanf(p + 1, "%d", &_y4m->pic_h) != 1) return -1;
got_h = 1; got_h = 1;
} } break;
break;
case 'F': { case 'F': {
if (sscanf(p + 1, "%d:%d", &_y4m->fps_n, &_y4m->fps_d) != 2) { if (sscanf(p + 1, "%d:%d", &_y4m->fps_n, &_y4m->fps_d) != 2) {
return -1; return -1;
} }
got_fps = 1; got_fps = 1;
} } break;
break;
case 'I': { case 'I': {
_y4m->interlace = p[1]; _y4m->interlace = p[1];
got_interlace = 1; got_interlace = 1;
} } break;
break;
case 'A': { case 'A': {
if (sscanf(p + 1, "%d:%d", &_y4m->par_n, &_y4m->par_d) != 2) { if (sscanf(p + 1, "%d:%d", &_y4m->par_n, &_y4m->par_d) != 2) {
return -1; return -1;
} }
got_par = 1; got_par = 1;
} } break;
break;
case 'C': { case 'C': {
if (q - p > 16) return -1; if (q - p > 16) return -1;
memcpy(_y4m->chroma_type, p + 1, q - p - 1); memcpy(_y4m->chroma_type, p + 1, q - p - 1);
_y4m->chroma_type[q - p - 1] = '\0'; _y4m->chroma_type[q - p - 1] = '\0';
got_chroma = 1; got_chroma = 1;
} } break;
break;
/*Ignore unknown tags.*/ /*Ignore unknown tags.*/
} }
} }
@ -116,8 +112,6 @@ static int y4m_parse_tags(y4m_input *_y4m, char *_tags) {
return 0; return 0;
} }
/*All anti-aliasing filters in the following conversion functions are based on /*All anti-aliasing filters in the following conversion functions are based on
one of two window functions: one of two window functions:
The 6-tap Lanczos window (for down-sampling and shifts): The 6-tap Lanczos window (for down-sampling and shifts):
@ -186,25 +180,36 @@ static int y4m_parse_tags(y4m_input *_y4m, char *_tags) {
lines, and they are vertically co-sited with the luma samples in both the lines, and they are vertically co-sited with the luma samples in both the
mpeg2 and jpeg cases (thus requiring no vertical resampling).*/ mpeg2 and jpeg cases (thus requiring no vertical resampling).*/
static void y4m_42xmpeg2_42xjpeg_helper(unsigned char *_dst, static void y4m_42xmpeg2_42xjpeg_helper(unsigned char *_dst,
const unsigned char *_src, int _c_w, int _c_h) { const unsigned char *_src, int _c_w,
int _c_h) {
int y; int y;
int x; int x;
for (y = 0; y < _c_h; y++) { for (y = 0; y < _c_h; y++) {
/*Filter: [4 -17 114 35 -9 1]/128, derived from a 6-tap Lanczos /*Filter: [4 -17 114 35 -9 1]/128, derived from a 6-tap Lanczos
window.*/ window.*/
for (x = 0; x < OC_MINI(_c_w, 2); x++) { for (x = 0; x < OC_MINI(_c_w, 2); x++) {
_dst[x] = (unsigned char)OC_CLAMPI(0, (4 * _src[0] - 17 * _src[OC_MAXI(x - 1, 0)] + _dst[x] = (unsigned char)OC_CLAMPI(
114 * _src[x] + 35 * _src[OC_MINI(x + 1, _c_w - 1)] - 9 * _src[OC_MINI(x + 2, _c_w - 1)] + 0, (4 * _src[0] - 17 * _src[OC_MAXI(x - 1, 0)] + 114 * _src[x] +
_src[OC_MINI(x + 3, _c_w - 1)] + 64) >> 7, 255); 35 * _src[OC_MINI(x + 1, _c_w - 1)] -
9 * _src[OC_MINI(x + 2, _c_w - 1)] +
_src[OC_MINI(x + 3, _c_w - 1)] + 64) >>
7,
255);
} }
for (; x < _c_w - 3; x++) { for (; x < _c_w - 3; x++) {
_dst[x] = (unsigned char)OC_CLAMPI(0, (4 * _src[x - 2] - 17 * _src[x - 1] + _dst[x] = (unsigned char)OC_CLAMPI(
114 * _src[x] + 35 * _src[x + 1] - 9 * _src[x + 2] + _src[x + 3] + 64) >> 7, 255); 0, (4 * _src[x - 2] - 17 * _src[x - 1] + 114 * _src[x] +
35 * _src[x + 1] - 9 * _src[x + 2] + _src[x + 3] + 64) >>
7,
255);
} }
for (; x < _c_w; x++) { for (; x < _c_w; x++) {
_dst[x] = (unsigned char)OC_CLAMPI(0, (4 * _src[x - 2] - 17 * _src[x - 1] + _dst[x] = (unsigned char)OC_CLAMPI(
114 * _src[x] + 35 * _src[OC_MINI(x + 1, _c_w - 1)] - 9 * _src[OC_MINI(x + 2, _c_w - 1)] + 0, (4 * _src[x - 2] - 17 * _src[x - 1] + 114 * _src[x] +
_src[_c_w - 1] + 64) >> 7, 255); 35 * _src[OC_MINI(x + 1, _c_w - 1)] -
9 * _src[OC_MINI(x + 2, _c_w - 1)] + _src[_c_w - 1] + 64) >>
7,
255);
} }
_dst += _c_w; _dst += _c_w;
_src += _c_w; _src += _c_w;
@ -302,53 +307,73 @@ static void y4m_convert_42xpaldv_42xjpeg(y4m_input *_y4m, unsigned char *_dst,
This is the same filter used above, but in the other order.*/ This is the same filter used above, but in the other order.*/
for (x = 0; x < c_w; x++) { for (x = 0; x < c_w; x++) {
for (y = 0; y < OC_MINI(c_h, 3); y++) { for (y = 0; y < OC_MINI(c_h, 3); y++) {
_dst[y * c_w] = (unsigned char)OC_CLAMPI(0, (tmp[0] _dst[y * c_w] = (unsigned char)OC_CLAMPI(
- 9 * tmp[OC_MAXI(y - 2, 0) * c_w] + 35 * tmp[OC_MAXI(y - 1, 0) * c_w] 0, (tmp[0] - 9 * tmp[OC_MAXI(y - 2, 0) * c_w] +
+ 114 * tmp[y * c_w] - 17 * tmp[OC_MINI(y + 1, c_h - 1) * c_w] 35 * tmp[OC_MAXI(y - 1, 0) * c_w] + 114 * tmp[y * c_w] -
+ 4 * tmp[OC_MINI(y + 2, c_h - 1) * c_w] + 64) >> 7, 255); 17 * tmp[OC_MINI(y + 1, c_h - 1) * c_w] +
4 * tmp[OC_MINI(y + 2, c_h - 1) * c_w] + 64) >>
7,
255);
} }
for (; y < c_h - 2; y++) { for (; y < c_h - 2; y++) {
_dst[y * c_w] = (unsigned char)OC_CLAMPI(0, (tmp[(y - 3) * c_w] _dst[y * c_w] = (unsigned char)OC_CLAMPI(
- 9 * tmp[(y - 2) * c_w] + 35 * tmp[(y - 1) * c_w] + 114 * tmp[y * c_w] 0, (tmp[(y - 3) * c_w] - 9 * tmp[(y - 2) * c_w] +
- 17 * tmp[(y + 1) * c_w] + 4 * tmp[(y + 2) * c_w] + 64) >> 7, 255); 35 * tmp[(y - 1) * c_w] + 114 * tmp[y * c_w] -
17 * tmp[(y + 1) * c_w] + 4 * tmp[(y + 2) * c_w] + 64) >>
7,
255);
} }
for (; y < c_h; y++) { for (; y < c_h; y++) {
_dst[y * c_w] = (unsigned char)OC_CLAMPI(0, (tmp[(y - 3) * c_w] _dst[y * c_w] = (unsigned char)OC_CLAMPI(
- 9 * tmp[(y - 2) * c_w] + 35 * tmp[(y - 1) * c_w] + 114 * tmp[y * c_w] 0, (tmp[(y - 3) * c_w] - 9 * tmp[(y - 2) * c_w] +
- 17 * tmp[OC_MINI(y + 1, c_h - 1) * c_w] + 4 * tmp[(c_h - 1) * c_w] + 64) >> 7, 255); 35 * tmp[(y - 1) * c_w] + 114 * tmp[y * c_w] -
17 * tmp[OC_MINI(y + 1, c_h - 1) * c_w] +
4 * tmp[(c_h - 1) * c_w] + 64) >>
7,
255);
} }
_dst++; _dst++;
tmp++; tmp++;
} }
_dst += c_sz - c_w; _dst += c_sz - c_w;
tmp -= c_w; tmp -= c_w;
} } break;
break;
case 2: { case 2: {
/*Slide C_r down a quarter-pel. /*Slide C_r down a quarter-pel.
This is the same as the horizontal filter.*/ This is the same as the horizontal filter.*/
for (x = 0; x < c_w; x++) { for (x = 0; x < c_w; x++) {
for (y = 0; y < OC_MINI(c_h, 2); y++) { for (y = 0; y < OC_MINI(c_h, 2); y++) {
_dst[y * c_w] = (unsigned char)OC_CLAMPI(0, (4 * tmp[0] _dst[y * c_w] = (unsigned char)OC_CLAMPI(
- 17 * tmp[OC_MAXI(y - 1, 0) * c_w] + 114 * tmp[y * c_w] 0,
+ 35 * tmp[OC_MINI(y + 1, c_h - 1) * c_w] - 9 * tmp[OC_MINI(y + 2, c_h - 1) * c_w] (4 * tmp[0] - 17 * tmp[OC_MAXI(y - 1, 0) * c_w] +
+ tmp[OC_MINI(y + 3, c_h - 1) * c_w] + 64) >> 7, 255); 114 * tmp[y * c_w] + 35 * tmp[OC_MINI(y + 1, c_h - 1) * c_w] -
9 * tmp[OC_MINI(y + 2, c_h - 1) * c_w] +
tmp[OC_MINI(y + 3, c_h - 1) * c_w] + 64) >>
7,
255);
} }
for (; y < c_h - 3; y++) { for (; y < c_h - 3; y++) {
_dst[y * c_w] = (unsigned char)OC_CLAMPI(0, (4 * tmp[(y - 2) * c_w] _dst[y * c_w] = (unsigned char)OC_CLAMPI(
- 17 * tmp[(y - 1) * c_w] + 114 * tmp[y * c_w] + 35 * tmp[(y + 1) * c_w] 0, (4 * tmp[(y - 2) * c_w] - 17 * tmp[(y - 1) * c_w] +
- 9 * tmp[(y + 2) * c_w] + tmp[(y + 3) * c_w] + 64) >> 7, 255); 114 * tmp[y * c_w] + 35 * tmp[(y + 1) * c_w] -
9 * tmp[(y + 2) * c_w] + tmp[(y + 3) * c_w] + 64) >>
7,
255);
} }
for (; y < c_h; y++) { for (; y < c_h; y++) {
_dst[y * c_w] = (unsigned char)OC_CLAMPI(0, (4 * tmp[(y - 2) * c_w] _dst[y * c_w] = (unsigned char)OC_CLAMPI(
- 17 * tmp[(y - 1) * c_w] + 114 * tmp[y * c_w] + 35 * tmp[OC_MINI(y + 1, c_h - 1) * c_w] 0,
- 9 * tmp[OC_MINI(y + 2, c_h - 1) * c_w] + tmp[(c_h - 1) * c_w] + 64) >> 7, 255); (4 * tmp[(y - 2) * c_w] - 17 * tmp[(y - 1) * c_w] +
114 * tmp[y * c_w] + 35 * tmp[OC_MINI(y + 1, c_h - 1) * c_w] -
9 * tmp[OC_MINI(y + 2, c_h - 1) * c_w] + tmp[(c_h - 1) * c_w] +
64) >>
7,
255);
} }
_dst++; _dst++;
tmp++; tmp++;
} }
} } break;
break;
} }
/*For actual interlaced material, this would have to be done separately on /*For actual interlaced material, this would have to be done separately on
each field, and the shift amounts would be different. each field, and the shift amounts would be different.
@ -363,27 +388,37 @@ static void y4m_convert_42xpaldv_42xjpeg(y4m_input *_y4m, unsigned char *_dst,
/*Perform vertical filtering to reduce a single plane from 4:2:2 to 4:2:0. /*Perform vertical filtering to reduce a single plane from 4:2:2 to 4:2:0.
This is used as a helper by several converation routines.*/ This is used as a helper by several converation routines.*/
static void y4m_422jpeg_420jpeg_helper(unsigned char *_dst, static void y4m_422jpeg_420jpeg_helper(unsigned char *_dst,
const unsigned char *_src, int _c_w, int _c_h) { const unsigned char *_src, int _c_w,
int _c_h) {
int y; int y;
int x; int x;
/*Filter: [3 -17 78 78 -17 3]/128, derived from a 6-tap Lanczos window.*/ /*Filter: [3 -17 78 78 -17 3]/128, derived from a 6-tap Lanczos window.*/
for (x = 0; x < _c_w; x++) { for (x = 0; x < _c_w; x++) {
for (y = 0; y < OC_MINI(_c_h, 2); y += 2) { for (y = 0; y < OC_MINI(_c_h, 2); y += 2) {
_dst[(y >> 1)*_c_w] = OC_CLAMPI(0, (64 * _src[0] _dst[(y >> 1) * _c_w] =
+ 78 * _src[OC_MINI(1, _c_h - 1) * _c_w] OC_CLAMPI(0, (64 * _src[0] + 78 * _src[OC_MINI(1, _c_h - 1) * _c_w] -
- 17 * _src[OC_MINI(2, _c_h - 1) * _c_w] 17 * _src[OC_MINI(2, _c_h - 1) * _c_w] +
+ 3 * _src[OC_MINI(3, _c_h - 1) * _c_w] + 64) >> 7, 255); 3 * _src[OC_MINI(3, _c_h - 1) * _c_w] + 64) >>
7,
255);
} }
for (; y < _c_h - 3; y += 2) { for (; y < _c_h - 3; y += 2) {
_dst[(y >> 1)*_c_w] = OC_CLAMPI(0, (3 * (_src[(y - 2) * _c_w] + _src[(y + 3) * _c_w]) _dst[(y >> 1) * _c_w] =
- 17 * (_src[(y - 1) * _c_w] + _src[(y + 2) * _c_w]) OC_CLAMPI(0, (3 * (_src[(y - 2) * _c_w] + _src[(y + 3) * _c_w]) -
+ 78 * (_src[y * _c_w] + _src[(y + 1) * _c_w]) + 64) >> 7, 255); 17 * (_src[(y - 1) * _c_w] + _src[(y + 2) * _c_w]) +
78 * (_src[y * _c_w] + _src[(y + 1) * _c_w]) + 64) >>
7,
255);
} }
for (; y < _c_h; y += 2) { for (; y < _c_h; y += 2) {
_dst[(y >> 1)*_c_w] = OC_CLAMPI(0, (3 * (_src[(y - 2) * _c_w] _dst[(y >> 1) * _c_w] = OC_CLAMPI(
+ _src[(_c_h - 1) * _c_w]) - 17 * (_src[(y - 1) * _c_w] 0,
+ _src[OC_MINI(y + 2, _c_h - 1) * _c_w]) (3 * (_src[(y - 2) * _c_w] + _src[(_c_h - 1) * _c_w]) -
+ 78 * (_src[y * _c_w] + _src[OC_MINI(y + 1, _c_h - 1) * _c_w]) + 64) >> 7, 255); 17 * (_src[(y - 1) * _c_w] + _src[OC_MINI(y + 2, _c_h - 1) * _c_w]) +
78 * (_src[y * _c_w] + _src[OC_MINI(y + 1, _c_h - 1) * _c_w]) +
64) >>
7,
255);
} }
_src++; _src++;
_dst++; _dst++;
@ -598,23 +633,42 @@ static void y4m_convert_411_420jpeg(y4m_input *_y4m, unsigned char *_dst,
/*Filters: [1 110 18 -1]/128 and [-3 50 86 -5]/128, both derived from a /*Filters: [1 110 18 -1]/128 and [-3 50 86 -5]/128, both derived from a
4-tap Mitchell window.*/ 4-tap Mitchell window.*/
for (x = 0; x < OC_MINI(c_w, 1); x++) { for (x = 0; x < OC_MINI(c_w, 1); x++) {
tmp[x << 1] = (unsigned char)OC_CLAMPI(0, (111 * _aux[0] tmp[x << 1] = (unsigned char)OC_CLAMPI(
+ 18 * _aux[OC_MINI(1, c_w - 1)] - _aux[OC_MINI(2, c_w - 1)] + 64) >> 7, 255); 0, (111 * _aux[0] + 18 * _aux[OC_MINI(1, c_w - 1)] -
tmp[x << 1 | 1] = (unsigned char)OC_CLAMPI(0, (47 * _aux[0] _aux[OC_MINI(2, c_w - 1)] + 64) >>
+ 86 * _aux[OC_MINI(1, c_w - 1)] - 5 * _aux[OC_MINI(2, c_w - 1)] + 64) >> 7, 255); 7,
255);
tmp[x << 1 | 1] = (unsigned char)OC_CLAMPI(
0, (47 * _aux[0] + 86 * _aux[OC_MINI(1, c_w - 1)] -
5 * _aux[OC_MINI(2, c_w - 1)] + 64) >>
7,
255);
} }
for (; x < c_w - 2; x++) { for (; x < c_w - 2; x++) {
tmp[x << 1] = (unsigned char)OC_CLAMPI(0, (_aux[x - 1] + 110 * _aux[x] tmp[x << 1] =
+ 18 * _aux[x + 1] - _aux[x + 2] + 64) >> 7, 255); (unsigned char)OC_CLAMPI(0, (_aux[x - 1] + 110 * _aux[x] +
tmp[x << 1 | 1] = (unsigned char)OC_CLAMPI(0, (-3 * _aux[x - 1] + 50 * _aux[x] 18 * _aux[x + 1] - _aux[x + 2] + 64) >>
+ 86 * _aux[x + 1] - 5 * _aux[x + 2] + 64) >> 7, 255); 7,
255);
tmp[x << 1 | 1] = (unsigned char)OC_CLAMPI(
0, (-3 * _aux[x - 1] + 50 * _aux[x] + 86 * _aux[x + 1] -
5 * _aux[x + 2] + 64) >>
7,
255);
} }
for (; x < c_w; x++) { for (; x < c_w; x++) {
tmp[x << 1] = (unsigned char)OC_CLAMPI(0, (_aux[x - 1] + 110 * _aux[x] tmp[x << 1] = (unsigned char)OC_CLAMPI(
+ 18 * _aux[OC_MINI(x + 1, c_w - 1)] - _aux[c_w - 1] + 64) >> 7, 255); 0, (_aux[x - 1] + 110 * _aux[x] +
18 * _aux[OC_MINI(x + 1, c_w - 1)] - _aux[c_w - 1] + 64) >>
7,
255);
if ((x << 1 | 1) < dst_c_w) { if ((x << 1 | 1) < dst_c_w) {
tmp[x << 1 | 1] = (unsigned char)OC_CLAMPI(0, (-3 * _aux[x - 1] + 50 * _aux[x] tmp[x << 1 | 1] = (unsigned char)OC_CLAMPI(
+ 86 * _aux[OC_MINI(x + 1, c_w - 1)] - 5 * _aux[c_w - 1] + 64) >> 7, 255); 0,
(-3 * _aux[x - 1] + 50 * _aux[x] +
86 * _aux[OC_MINI(x + 1, c_w - 1)] - 5 * _aux[c_w - 1] + 64) >>
7,
255);
} }
} }
tmp += dst_c_w; tmp += dst_c_w;
@ -656,18 +710,27 @@ static void y4m_convert_444_420jpeg(y4m_input *_y4m, unsigned char *_dst,
/*Filter: [3 -17 78 78 -17 3]/128, derived from a 6-tap Lanczos window.*/ /*Filter: [3 -17 78 78 -17 3]/128, derived from a 6-tap Lanczos window.*/
for (y = 0; y < c_h; y++) { for (y = 0; y < c_h; y++) {
for (x = 0; x < OC_MINI(c_w, 2); x += 2) { for (x = 0; x < OC_MINI(c_w, 2); x += 2) {
tmp[x >> 1] = OC_CLAMPI(0, (64 * _aux[0] + 78 * _aux[OC_MINI(1, c_w - 1)] tmp[x >> 1] =
- 17 * _aux[OC_MINI(2, c_w - 1)] OC_CLAMPI(0, (64 * _aux[0] + 78 * _aux[OC_MINI(1, c_w - 1)] -
+ 3 * _aux[OC_MINI(3, c_w - 1)] + 64) >> 7, 255); 17 * _aux[OC_MINI(2, c_w - 1)] +
3 * _aux[OC_MINI(3, c_w - 1)] + 64) >>
7,
255);
} }
for (; x < c_w - 3; x += 2) { for (; x < c_w - 3; x += 2) {
tmp[x >> 1] = OC_CLAMPI(0, (3 * (_aux[x - 2] + _aux[x + 3]) tmp[x >> 1] = OC_CLAMPI(0, (3 * (_aux[x - 2] + _aux[x + 3]) -
- 17 * (_aux[x - 1] + _aux[x + 2]) + 78 * (_aux[x] + _aux[x + 1]) + 64) >> 7, 255); 17 * (_aux[x - 1] + _aux[x + 2]) +
78 * (_aux[x] + _aux[x + 1]) + 64) >>
7,
255);
} }
for (; x < c_w; x += 2) { for (; x < c_w; x += 2) {
tmp[x >> 1] = OC_CLAMPI(0, (3 * (_aux[x - 2] + _aux[c_w - 1]) - tmp[x >> 1] = OC_CLAMPI(
0, (3 * (_aux[x - 2] + _aux[c_w - 1]) -
17 * (_aux[x - 1] + _aux[OC_MINI(x + 2, c_w - 1)]) + 17 * (_aux[x - 1] + _aux[OC_MINI(x + 2, c_w - 1)]) +
78 * (_aux[x] + _aux[OC_MINI(x + 1, c_w - 1)]) + 64) >> 7, 255); 78 * (_aux[x] + _aux[OC_MINI(x + 1, c_w - 1)]) + 64) >>
7,
255);
} }
tmp += dst_c_w; tmp += dst_c_w;
_aux += c_w; _aux += c_w;
@ -733,10 +796,12 @@ int y4m_input_open(y4m_input *_y4m, FILE *_fin, char *_skip, int _nskip,
return ret; return ret;
} }
if (_y4m->interlace == '?') { if (_y4m->interlace == '?') {
fprintf(stderr, "Warning: Input video interlacing format unknown; " fprintf(stderr,
"Warning: Input video interlacing format unknown; "
"assuming progressive scan.\n"); "assuming progressive scan.\n");
} else if (_y4m->interlace != 'p') { } else if (_y4m->interlace != 'p') {
fprintf(stderr, "Input video is interlaced; " fprintf(stderr,
"Input video is interlaced; "
"Only progressive scan handled.\n"); "Only progressive scan handled.\n");
return -1; return -1;
} }
@ -745,9 +810,11 @@ int y4m_input_open(y4m_input *_y4m, FILE *_fin, char *_skip, int _nskip,
_y4m->bit_depth = 8; _y4m->bit_depth = 8;
if (strcmp(_y4m->chroma_type, "420") == 0 || if (strcmp(_y4m->chroma_type, "420") == 0 ||
strcmp(_y4m->chroma_type, "420jpeg") == 0) { strcmp(_y4m->chroma_type, "420jpeg") == 0) {
_y4m->src_c_dec_h = _y4m->dst_c_dec_h = _y4m->src_c_dec_v = _y4m->dst_c_dec_v = 2; _y4m->src_c_dec_h = _y4m->dst_c_dec_h = _y4m->src_c_dec_v =
_y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h _y4m->dst_c_dec_v = 2;
+ 2 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2); _y4m->dst_buf_read_sz =
_y4m->pic_w * _y4m->pic_h +
2 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2);
/* Natively supported: no conversion required. */ /* Natively supported: no conversion required. */
_y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0; _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
_y4m->convert = y4m_convert_null; _y4m->convert = y4m_convert_null;
@ -756,9 +823,9 @@ int y4m_input_open(y4m_input *_y4m, FILE *_fin, char *_skip, int _nskip,
_y4m->dst_c_dec_h = 2; _y4m->dst_c_dec_h = 2;
_y4m->src_c_dec_v = 2; _y4m->src_c_dec_v = 2;
_y4m->dst_c_dec_v = 2; _y4m->dst_c_dec_v = 2;
_y4m->dst_buf_read_sz = 2 * (_y4m->pic_w * _y4m->pic_h + _y4m->dst_buf_read_sz =
2 * ((_y4m->pic_w + 1) / 2) * 2 * (_y4m->pic_w * _y4m->pic_h +
((_y4m->pic_h + 1) / 2)); 2 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2));
/* Natively supported: no conversion required. */ /* Natively supported: no conversion required. */
_y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0; _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
_y4m->convert = y4m_convert_null; _y4m->convert = y4m_convert_null;
@ -774,9 +841,9 @@ int y4m_input_open(y4m_input *_y4m, FILE *_fin, char *_skip, int _nskip,
_y4m->dst_c_dec_h = 2; _y4m->dst_c_dec_h = 2;
_y4m->src_c_dec_v = 2; _y4m->src_c_dec_v = 2;
_y4m->dst_c_dec_v = 2; _y4m->dst_c_dec_v = 2;
_y4m->dst_buf_read_sz = 2 * (_y4m->pic_w * _y4m->pic_h + _y4m->dst_buf_read_sz =
2 * ((_y4m->pic_w + 1) / 2) * 2 * (_y4m->pic_w * _y4m->pic_h +
((_y4m->pic_h + 1) / 2)); 2 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2));
/* Natively supported: no conversion required. */ /* Natively supported: no conversion required. */
_y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0; _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
_y4m->convert = y4m_convert_null; _y4m->convert = y4m_convert_null;
@ -788,20 +855,23 @@ int y4m_input_open(y4m_input *_y4m, FILE *_fin, char *_skip, int _nskip,
return -1; return -1;
} }
} else if (strcmp(_y4m->chroma_type, "420mpeg2") == 0) { } else if (strcmp(_y4m->chroma_type, "420mpeg2") == 0) {
_y4m->src_c_dec_h = _y4m->dst_c_dec_h = _y4m->src_c_dec_v = _y4m->dst_c_dec_v = 2; _y4m->src_c_dec_h = _y4m->dst_c_dec_h = _y4m->src_c_dec_v =
_y4m->dst_c_dec_v = 2;
_y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h; _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
/*Chroma filter required: read into the aux buf first.*/ /*Chroma filter required: read into the aux buf first.*/
_y4m->aux_buf_sz = _y4m->aux_buf_read_sz = _y4m->aux_buf_sz = _y4m->aux_buf_read_sz =
2 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2); 2 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2);
_y4m->convert = y4m_convert_42xmpeg2_42xjpeg; _y4m->convert = y4m_convert_42xmpeg2_42xjpeg;
} else if (strcmp(_y4m->chroma_type, "420paldv") == 0) { } else if (strcmp(_y4m->chroma_type, "420paldv") == 0) {
_y4m->src_c_dec_h = _y4m->dst_c_dec_h = _y4m->src_c_dec_v = _y4m->dst_c_dec_v = 2; _y4m->src_c_dec_h = _y4m->dst_c_dec_h = _y4m->src_c_dec_v =
_y4m->dst_c_dec_v = 2;
_y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h; _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
/*Chroma filter required: read into the aux buf first. /*Chroma filter required: read into the aux buf first.
We need to make two filter passes, so we need some extra space in the We need to make two filter passes, so we need some extra space in the
aux buffer.*/ aux buffer.*/
_y4m->aux_buf_sz = 3 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2); _y4m->aux_buf_sz = 3 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2);
_y4m->aux_buf_read_sz = 2 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2); _y4m->aux_buf_read_sz =
2 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2);
_y4m->convert = y4m_convert_42xpaldv_42xjpeg; _y4m->convert = y4m_convert_42xpaldv_42xjpeg;
} else if (strcmp(_y4m->chroma_type, "422jpeg") == 0) { } else if (strcmp(_y4m->chroma_type, "422jpeg") == 0) {
_y4m->src_c_dec_h = _y4m->dst_c_dec_h = 2; _y4m->src_c_dec_h = _y4m->dst_c_dec_h = 2;
@ -809,7 +879,8 @@ int y4m_input_open(y4m_input *_y4m, FILE *_fin, char *_skip, int _nskip,
_y4m->dst_c_dec_v = 2; _y4m->dst_c_dec_v = 2;
_y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h; _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
/*Chroma filter required: read into the aux buf first.*/ /*Chroma filter required: read into the aux buf first.*/
_y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 2 * ((_y4m->pic_w + 1) / 2) * _y4m->pic_h; _y4m->aux_buf_sz = _y4m->aux_buf_read_sz =
2 * ((_y4m->pic_w + 1) / 2) * _y4m->pic_h;
_y4m->convert = y4m_convert_422jpeg_420jpeg; _y4m->convert = y4m_convert_422jpeg_420jpeg;
} else if (strcmp(_y4m->chroma_type, "422") == 0) { } else if (strcmp(_y4m->chroma_type, "422") == 0) {
_y4m->src_c_dec_h = 2; _y4m->src_c_dec_h = 2;
@ -822,16 +893,16 @@ int y4m_input_open(y4m_input *_y4m, FILE *_fin, char *_skip, int _nskip,
We need to make two filter passes, so we need some extra space in the We need to make two filter passes, so we need some extra space in the
aux buffer.*/ aux buffer.*/
_y4m->aux_buf_read_sz = 2 * ((_y4m->pic_w + 1) / 2) * _y4m->pic_h; _y4m->aux_buf_read_sz = 2 * ((_y4m->pic_w + 1) / 2) * _y4m->pic_h;
_y4m->aux_buf_sz = _y4m->aux_buf_read_sz + _y4m->aux_buf_sz =
((_y4m->pic_w + 1) / 2) * _y4m->pic_h; _y4m->aux_buf_read_sz + ((_y4m->pic_w + 1) / 2) * _y4m->pic_h;
_y4m->convert = y4m_convert_422_420jpeg; _y4m->convert = y4m_convert_422_420jpeg;
} else { } else {
_y4m->vpx_fmt = VPX_IMG_FMT_I422; _y4m->vpx_fmt = VPX_IMG_FMT_I422;
_y4m->bps = 16; _y4m->bps = 16;
_y4m->dst_c_dec_h = _y4m->src_c_dec_h; _y4m->dst_c_dec_h = _y4m->src_c_dec_h;
_y4m->dst_c_dec_v = _y4m->src_c_dec_v; _y4m->dst_c_dec_v = _y4m->src_c_dec_v;
_y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h _y4m->dst_buf_read_sz =
+ 2 * ((_y4m->pic_w + 1) / 2) * _y4m->pic_h; _y4m->pic_w * _y4m->pic_h + 2 * ((_y4m->pic_w + 1) / 2) * _y4m->pic_h;
/*Natively supported: no conversion required.*/ /*Natively supported: no conversion required.*/
_y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0; _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
_y4m->convert = y4m_convert_null; _y4m->convert = y4m_convert_null;
@ -878,7 +949,8 @@ int y4m_input_open(y4m_input *_y4m, FILE *_fin, char *_skip, int _nskip,
We need to make two filter passes, so we need some extra space in the We need to make two filter passes, so we need some extra space in the
aux buffer.*/ aux buffer.*/
_y4m->aux_buf_read_sz = 2 * ((_y4m->pic_w + 3) / 4) * _y4m->pic_h; _y4m->aux_buf_read_sz = 2 * ((_y4m->pic_w + 3) / 4) * _y4m->pic_h;
_y4m->aux_buf_sz = _y4m->aux_buf_read_sz + ((_y4m->pic_w + 1) / 2) * _y4m->pic_h; _y4m->aux_buf_sz =
_y4m->aux_buf_read_sz + ((_y4m->pic_w + 1) / 2) * _y4m->pic_h;
_y4m->convert = y4m_convert_411_420jpeg; _y4m->convert = y4m_convert_411_420jpeg;
} else if (strcmp(_y4m->chroma_type, "444") == 0) { } else if (strcmp(_y4m->chroma_type, "444") == 0) {
_y4m->src_c_dec_h = 1; _y4m->src_c_dec_h = 1;
@ -891,8 +963,8 @@ int y4m_input_open(y4m_input *_y4m, FILE *_fin, char *_skip, int _nskip,
We need to make two filter passes, so we need some extra space in the We need to make two filter passes, so we need some extra space in the
aux buffer.*/ aux buffer.*/
_y4m->aux_buf_read_sz = 2 * _y4m->pic_w * _y4m->pic_h; _y4m->aux_buf_read_sz = 2 * _y4m->pic_w * _y4m->pic_h;
_y4m->aux_buf_sz = _y4m->aux_buf_read_sz + _y4m->aux_buf_sz =
((_y4m->pic_w + 1) / 2) * _y4m->pic_h; _y4m->aux_buf_read_sz + ((_y4m->pic_w + 1) / 2) * _y4m->pic_h;
_y4m->convert = y4m_convert_444_420jpeg; _y4m->convert = y4m_convert_444_420jpeg;
} else { } else {
_y4m->vpx_fmt = VPX_IMG_FMT_I444; _y4m->vpx_fmt = VPX_IMG_FMT_I444;
@ -971,8 +1043,9 @@ int y4m_input_open(y4m_input *_y4m, FILE *_fin, char *_skip, int _nskip,
} }
/*The size of the final frame buffers is always computed from the /*The size of the final frame buffers is always computed from the
destination chroma decimation type.*/ destination chroma decimation type.*/
_y4m->dst_buf_sz = _y4m->pic_w * _y4m->pic_h _y4m->dst_buf_sz =
+ 2 * ((_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h) * _y4m->pic_w * _y4m->pic_h +
2 * ((_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h) *
((_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v); ((_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v);
if (_y4m->bit_depth == 8) if (_y4m->bit_depth == 8)
_y4m->dst_buf = (unsigned char *)malloc(_y4m->dst_buf_sz); _y4m->dst_buf = (unsigned char *)malloc(_y4m->dst_buf_sz);
@ -1005,7 +1078,8 @@ int y4m_input_fetch_frame(y4m_input *_y4m, FILE *_fin, vpx_image_t *_img) {
if (frame[5] != '\n') { if (frame[5] != '\n') {
char c; char c;
int j; int j;
for (j = 0; j < 79 && file_read(&c, 1, _fin) && c != '\n'; j++) {} for (j = 0; j < 79 && file_read(&c, 1, _fin) && c != '\n'; j++) {
}
if (j == 79) { if (j == 79) {
fprintf(stderr, "Error parsing Y4M frame header\n"); fprintf(stderr, "Error parsing Y4M frame header\n");
return -1; return -1;

View File

@ -21,17 +21,11 @@
extern "C" { extern "C" {
#endif #endif
typedef struct y4m_input y4m_input; typedef struct y4m_input y4m_input;
/*The function used to perform chroma conversion.*/ /*The function used to perform chroma conversion.*/
typedef void (*y4m_convert_func)(y4m_input *_y4m, typedef void (*y4m_convert_func)(y4m_input *_y4m, unsigned char *_dst,
unsigned char *_dst, unsigned char *_src); unsigned char *_src);
struct y4m_input { struct y4m_input {
int pic_w; int pic_w;