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

116
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,42 +21,36 @@ 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;
a.argv = argv; a.argv = argv;
a.argv_step = 1; a.argv_step = 1;
a.name = NULL; a.name = NULL;
a.val = NULL; a.val = NULL;
a.def = NULL; a.def = NULL;
return a; return a;
} }
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,9 +86,8 @@ 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 };
for (; *defs; defs++) { for (; *defs; defs++) {
const struct arg_def *def = *defs; const struct arg_def *def = *defs;
@ -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,59 +112,53 @@ 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;
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;
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 */
}; };
struct vpx_rational arg_parse_rational(const struct arg *arg) { struct vpx_rational arg_parse_rational(const struct arg *arg) {
long int rawval; long int rawval;
char *endptr; char *endptr;
struct vpx_rational rat; struct vpx_rational rat;
/* parse numerator */ /* parse numerator */
rawval = strtol(arg->val, &endptr, 10); rawval = strtol(arg->val, &endptr, 10);
@ -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,40 +178,37 @@ 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;
char *endptr; char *endptr;
/* First see if the value can be parsed as a raw value */ /* First see if the value can be parsed as a raw value */
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') {
/* 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);
} }

27
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>
@ -18,29 +17,33 @@ extern "C" {
#endif #endif
struct arg { struct arg {
char **argv; char **argv;
const char *name; const char *name;
const char *val; const char *val;
unsigned int argv_step; unsigned int argv_step;
const struct arg_def *def; const struct arg_def *def;
}; };
struct arg_enum_list { 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;
const char *long_name; const char *long_name;
int has_val; int has_val;
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,11 +18,11 @@ 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" */
#endif #endif
#endif // IVFDEC_H_ #endif // IVFDEC_H_

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,17 +19,15 @@ 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);
void ivf_write_frame_size(FILE *outfile, size_t frame_size); void ivf_write_frame_size(FILE *outfile, size_t frame_size);
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */
#endif #endif
#endif // IVFENC_H_ #endif // IVFENC_H_

View File

@ -20,19 +20,17 @@
* Still in the public domain. * Still in the public domain.
*/ */
#include <string.h> /* for memcpy() */ #include <string.h> /* for memcpy() */
#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 */
@ -71,9 +67,9 @@ MD5Update(struct MD5Context *ctx, md5byte const *buf, unsigned len) {
t = ctx->bytes[0]; t = ctx->bytes[0];
if ((ctx->bytes[0] = t + len) < t) if ((ctx->bytes[0] = t + len) < t)
ctx->bytes[1]++; /* Carry from low to high */ ctx->bytes[1]++; /* Carry from low to high */
t = 64 - (t & 0x3f); /* Space available in ctx->in (at least 1) */ t = 64 - (t & 0x3f); /* Space available in ctx->in (at least 1) */
if (t > len) { if (t > len) {
memcpy((md5byte *)ctx->in + 64 - t, buf, len); memcpy((md5byte *)ctx->in + 64 - t, buf, len);
@ -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;
@ -115,7 +110,7 @@ MD5Final(md5byte digest[16], struct MD5Context *ctx) {
/* Bytes of padding needed to make 56 bytes (-8..55) */ /* Bytes of padding needed to make 56 bytes (-8..55) */
count = 56 - 1 - count; count = 56 - 1 - count;
if (count < 0) { /* Padding forces an extra block */ if (count < 0) { /* Padding forces an extra block */
memset(p, 0, count + 8); memset(p, 0, count + 8);
byteSwap(ctx->in, 16); byteSwap(ctx->in, 16);
MD5Transform(ctx->buf, ctx->in); MD5Transform(ctx->buf, ctx->in);
@ -147,8 +142,8 @@ MD5Final(md5byte digest[16], struct MD5Context *ctx) {
#define F4(x, y, z) (y ^ (x | ~z)) #define F4(x, y, z) (y ^ (x | ~z))
/* This is the central step in the MD5 algorithm. */ /* This is the central step in the MD5 algorithm. */
#define MD5STEP(f,w,x,y,z,in,s) \ #define MD5STEP(f, w, x, y, z, in, s) \
(w += f(x,y,z) + in, w = (w<<s | w>>(32-s)) + x) (w += f(x, y, z) + in, w = (w << s | w >> (32 - s)) + x)
#if defined(__clang__) && defined(__has_attribute) #if defined(__clang__) && defined(__has_attribute)
#if __has_attribute(no_sanitize) #if __has_attribute(no_sanitize)
@ -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;
@ -78,18 +77,16 @@ void update_rate_histogram(struct rate_hist *hist,
int64_t avg_bitrate = 0; int64_t avg_bitrate = 0;
int64_t sum_sz = 0; int64_t sum_sz = 0;
const int64_t now = pkt->data.frame.pts * 1000 * const int64_t now = pkt->data.frame.pts * 1000 *
(uint64_t)cfg->g_timebase.num / (uint64_t)cfg->g_timebase.num /
(uint64_t)cfg->g_timebase.den; (uint64_t)cfg->g_timebase.den;
int idx = hist->frames++ % hist->samples; int idx = hist->frames++ % hist->samples;
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

@ -29,23 +29,22 @@
#include <fcntl.h> #include <fcntl.h>
#ifdef __OS2__ #ifdef __OS2__
#define _setmode setmode #define _setmode setmode
#define _fileno fileno #define _fileno fileno
#define _O_BINARY O_BINARY #define _O_BINARY O_BINARY
#endif #endif
#endif #endif
#define LOG_ERROR(label) do {\ #define LOG_ERROR(label) \
const char *l = label;\ do { \
va_list ap;\ const char *l = label; \
va_start(ap, fmt);\ va_list ap; \
if (l)\ va_start(ap, fmt); \
fprintf(stderr, "%s: ", l);\ if (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;
@ -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) {
@ -134,11 +131,11 @@ int read_yuv_frame(struct VpxInputContext *input_ctx, vpx_image_t *yuv_frame) {
static const VpxInterface vpx_encoders[] = { static const VpxInterface vpx_encoders[] = {
#if CONFIG_VP8_ENCODER #if CONFIG_VP8_ENCODER
{"vp8", VP8_FOURCC, &vpx_codec_vp8_cx}, { "vp8", VP8_FOURCC, &vpx_codec_vp8_cx },
#endif #endif
#if CONFIG_VP9_ENCODER #if CONFIG_VP9_ENCODER
{"vp9", VP9_FOURCC, &vpx_codec_vp9_cx}, { "vp9", VP9_FOURCC, &vpx_codec_vp9_cx },
#endif #endif
}; };
@ -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;
@ -168,11 +162,11 @@ const VpxInterface *get_vpx_encoder_by_name(const char *name) {
static const VpxInterface vpx_decoders[] = { static const VpxInterface vpx_decoders[] = {
#if CONFIG_VP8_DECODER #if CONFIG_VP8_DECODER
{"vp8", VP8_FOURCC, &vpx_codec_vp8_dx}, { "vp8", VP8_FOURCC, &vpx_codec_vp8_dx },
#endif #endif
#if CONFIG_VP9_DECODER #if CONFIG_VP9_DECODER
{"vp9", VP9_FOURCC, &vpx_codec_vp9_dx}, { "vp9", VP9_FOURCC, &vpx_codec_vp9_dx },
#endif #endif
}; };
@ -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;
@ -220,7 +210,7 @@ int vpx_img_plane_width(const vpx_image_t *img, int plane) {
} }
int vpx_img_plane_height(const vpx_image_t *img, int plane) { int vpx_img_plane_height(const vpx_image_t *img, int plane) {
if (plane > 0 && img->y_chroma_shift > 0) if (plane > 0 && img->y_chroma_shift > 0)
return (img->d_h + 1) >> img->y_chroma_shift; return (img->d_h + 1) >> img->y_chroma_shift;
else else
return img->d_h; return img->d_h;
@ -233,7 +223,7 @@ void vpx_img_write(const vpx_image_t *img, FILE *file) {
const unsigned char *buf = img->planes[plane]; const unsigned char *buf = img->planes[plane];
const int stride = img->stride[plane]; const int stride = img->stride[plane];
const int w = vpx_img_plane_width(img, plane) * const int w = vpx_img_plane_width(img, plane) *
((img->fmt & VPX_IMG_FMT_HIGHBITDEPTH) ? 2 : 1); ((img->fmt & VPX_IMG_FMT_HIGHBITDEPTH) ? 2 : 1);
const int h = vpx_img_plane_height(img, plane); const int h = vpx_img_plane_height(img, plane);
int y; int y;
@ -251,13 +241,12 @@ int vpx_img_read(vpx_image_t *img, FILE *file) {
unsigned char *buf = img->planes[plane]; unsigned char *buf = img->planes[plane];
const int stride = img->stride[plane]; const int stride = img->stride[plane];
const int w = vpx_img_plane_width(img, plane) * const int w = vpx_img_plane_width(img, plane) *
((img->fmt & VPX_IMG_FMT_HIGHBITDEPTH) ? 2 : 1); ((img->fmt & VPX_IMG_FMT_HIGHBITDEPTH) ? 2 : 1);
const int h = vpx_img_plane_height(img, plane); const int h = vpx_img_plane_height(img, plane);
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,24 +30,24 @@
/* MinGW uses f{seek,tell}o64 for large files. */ /* MinGW uses f{seek,tell}o64 for large files. */
#define fseeko fseeko64 #define fseeko fseeko64
#define ftello ftello64 #define ftello ftello64
#endif /* _WIN32 */ #endif /* _WIN32 */
#if CONFIG_OS_SUPPORT #if CONFIG_OS_SUPPORT
#if defined(_MSC_VER) #if defined(_MSC_VER)
#include <io.h> /* NOLINT */ #include <io.h> /* NOLINT */
#define isatty _isatty #define isatty _isatty
#define fileno _fileno #define fileno _fileno
#else #else
#include <unistd.h> /* NOLINT */ #include <unistd.h> /* NOLINT */
#endif /* _MSC_VER */ #endif /* _MSC_VER */
#endif /* CONFIG_OS_SUPPORT */ #endif /* CONFIG_OS_SUPPORT */
/* Use 32-bit file operations in WebM file format when building ARM /* Use 32-bit file operations in WebM file format when building ARM
* executables (.axf) with RVCT. */ * executables (.axf) with RVCT. */
#if !CONFIG_OS_SUPPORT #if !CONFIG_OS_SUPPORT
#define fseeko fseek #define fseeko fseek
#define ftello ftell #define ftello ftell
#endif /* CONFIG_OS_SUPPORT */ #endif /* CONFIG_OS_SUPPORT */
#define LITERALU64(hi, lo) ((((uint64_t)hi) << 32) | lo) #define LITERALU64(hi, lo) ((((uint64_t)hi) << 32) | lo)
@ -55,7 +55,7 @@
#define PATH_MAX 512 #define PATH_MAX 512
#endif #endif
#define IVF_FRAME_HDR_SZ (4 + 8) /* 4 byte size + 8 byte timestamp */ #define IVF_FRAME_HDR_SZ (4 + 8) /* 4 byte size + 8 byte timestamp */
#define IVF_FILE_HDR_SZ 32 #define IVF_FILE_HDR_SZ 32
#define RAW_FRAME_HDR_SZ sizeof(uint32_t) #define RAW_FRAME_HDR_SZ sizeof(uint32_t)
@ -157,7 +157,7 @@ void vpx_img_truncate_16_to_8(vpx_image_t *dst, vpx_image_t *src);
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */
#endif #endif
#endif // TOOLS_COMMON_H_ #endif // TOOLS_COMMON_H_

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"

519
vpxdec.c
View File

@ -47,134 +47,145 @@ 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
static INLINE int libyuv_scale(vpx_image_t *src, vpx_image_t *dst, static INLINE int libyuv_scale(vpx_image_t *src, vpx_image_t *dst,
FilterModeEnum mode) { FilterModeEnum mode) {
#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;
} }
} }
@ -279,7 +287,7 @@ static void update_image_md5(const vpx_image_t *img, const int planes[3],
const unsigned char *buf = img->planes[plane]; const unsigned char *buf = img->planes[plane];
const int stride = img->stride[plane]; const int stride = img->stride[plane];
const int w = vpx_img_plane_width(img, plane) * const int w = vpx_img_plane_width(img, plane) *
((img->fmt & VPX_IMG_FMT_HIGHBITDEPTH) ? 2 : 1); ((img->fmt & VPX_IMG_FMT_HIGHBITDEPTH) ? 2 : 1);
const int h = vpx_img_plane_height(img, plane); const int h = vpx_img_plane_height(img, plane);
for (y = 0; y < h; ++y) { for (y = 0; y < h; ++y) {
@ -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;
@ -345,13 +353,13 @@ static int file_is_raw(struct VpxInputContext *input) {
static void show_progress(int frame_in, int frame_out, uint64_t dx_time) { static void show_progress(int frame_in, int frame_out, uint64_t dx_time) {
fprintf(stderr, fprintf(stderr,
"%d decoded frames/%d showed frames in %"PRId64" us (%.2f fps)\r", "%d decoded frames/%d showed frames in %" PRId64 " us (%.2f fps)\r",
frame_in, frame_out, dx_time, frame_in, frame_out, dx_time,
(double)frame_out * 1000000.0 / (double)dx_time); (double)frame_out * 1000000.0 / (double)dx_time);
} }
struct ExternalFrameBuffer { struct ExternalFrameBuffer {
uint8_t* data; uint8_t *data;
size_t size; size_t size;
int in_use; int in_use;
}; };
@ -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,65 +505,64 @@ 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
static int main_loop(int argc, const char **argv_) { static int main_loop(int argc, const char **argv_) {
vpx_codec_ctx_t decoder; vpx_codec_ctx_t decoder;
char *fn = NULL; char *fn = NULL;
int i; int i;
uint8_t *buf = NULL; uint8_t *buf = NULL;
size_t bytes_in_buffer = 0, buffer_size = 0; size_t bytes_in_buffer = 0, buffer_size = 0;
FILE *infile; FILE *infile;
int frame_in = 0, frame_out = 0, flipuv = 0, noblit = 0; int frame_in = 0, frame_out = 0, flipuv = 0, noblit = 0;
int do_md5 = 0, progress = 0, frame_parallel = 0; int do_md5 = 0, progress = 0, frame_parallel = 0;
int stop_after = 0, postproc = 0, summary = 0, quiet = 1; int stop_after = 0, postproc = 0, summary = 0, quiet = 1;
int arg_skip = 0; int arg_skip = 0;
int ec_enabled = 0; int ec_enabled = 0;
int keep_going = 0; int keep_going = 0;
const VpxInterface *interface = NULL; const VpxInterface *interface = NULL;
const VpxInterface *fourcc_interface = NULL; const VpxInterface *fourcc_interface = NULL;
uint64_t dx_time = 0; uint64_t dx_time = 0;
struct arg arg; struct arg arg;
char **argv, **argi, **argj; char **argv, **argi, **argj;
int single_file; int single_file;
int use_y4m = 1; int use_y4m = 1;
int opt_yv12 = 0; int opt_yv12 = 0;
int opt_i420 = 0; int opt_i420 = 0;
vpx_codec_dec_cfg_t cfg = {0, 0, 0}; vpx_codec_dec_cfg_t cfg = { 0, 0, 0 };
#if CONFIG_VP9_HIGHBITDEPTH #if CONFIG_VP9_HIGHBITDEPTH
unsigned int output_bit_depth = 0; unsigned int output_bit_depth = 0;
#endif #endif
#if CONFIG_VP8_DECODER #if CONFIG_VP8_DECODER
vp8_postproc_cfg_t vp8_pp_cfg = {0}; vp8_postproc_cfg_t vp8_pp_cfg = { 0 };
int vp8_dbg_color_ref_frame = 0; int vp8_dbg_color_ref_frame = 0;
int vp8_dbg_color_mb_modes = 0; int vp8_dbg_color_mb_modes = 0;
int vp8_dbg_color_b_modes = 0; int vp8_dbg_color_b_modes = 0;
int vp8_dbg_display_mv = 0; int vp8_dbg_display_mv = 0;
#endif #endif
int frames_corrupted = 0; int frames_corrupted = 0;
int dec_flags = 0; int dec_flags = 0;
int do_scale = 0; int do_scale = 0;
vpx_image_t *scaled_img = NULL; vpx_image_t *scaled_img = NULL;
#if CONFIG_VP9_HIGHBITDEPTH #if CONFIG_VP9_HIGHBITDEPTH
vpx_image_t *img_shifted = NULL; vpx_image_t *img_shifted = NULL;
#endif #endif
int frame_avail, got_data, flush_decoder = 0; int frame_avail, got_data, flush_decoder = 0;
int num_external_frame_buffers = 0; int num_external_frame_buffers = 0;
struct ExternalFrameBufferList ext_fb_list = {0, NULL}; struct ExternalFrameBufferList ext_fb_list = { 0, NULL };
const char *outfile_pattern = NULL; const char *outfile_pattern = NULL;
char outfile_name[PATH_MAX] = {0}; char outfile_name[PATH_MAX] = { 0 };
FILE *outfile = NULL; FILE *outfile = NULL;
MD5Context md5_ctx; MD5Context md5_ctx;
unsigned char md5_digest[16]; unsigned char md5_digest[16];
struct VpxDecInputContext input = {NULL, NULL}; struct VpxDecInputContext input = { NULL, NULL };
struct VpxInputContext vpx_input_ctx; struct VpxInputContext vpx_input_ctx;
#if CONFIG_WEBM_IO #if CONFIG_WEBM_IO
struct WebmInputContext webm_ctx; struct WebmInputContext webm_ctx;
@ -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,9 +832,9 @@ 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));
return EXIT_FAILURE; return EXIT_FAILURE;
@ -877,10 +846,10 @@ static int main_loop(int argc, const char **argv_) {
/* Decode file */ /* Decode file */
while (frame_avail || got_data) { while (frame_avail || got_data) {
vpx_codec_iter_t iter = NULL; vpx_codec_iter_t iter = NULL;
vpx_image_t *img; vpx_image_t *img;
struct vpx_usec_timer timer; struct vpx_usec_timer timer;
int corrupted = 0; int corrupted = 0;
frame_avail = 0; frame_avail = 0;
if (!stop_after || frame_in < stop_after) { if (!stop_after || frame_in < stop_after) {
@ -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,17 +899,15 @@ 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 };
const int PLANES_YVU[] = {VPX_PLANE_Y, VPX_PLANE_V, VPX_PLANE_U}; const int PLANES_YVU[] = { VPX_PLANE_Y, VPX_PLANE_V, VPX_PLANE_U };
const int *planes = flipuv ? PLANES_YVU : PLANES_YUV; const int *planes = flipuv ? PLANES_YVU : PLANES_YUV;
if (do_scale) { if (do_scale) {
@ -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);
@ -1017,7 +983,7 @@ static int main_loop(int argc, const char **argv_) {
if (single_file) { if (single_file) {
if (use_y4m) { if (use_y4m) {
char buf[Y4M_BUFFER_SIZE] = {0}; char buf[Y4M_BUFFER_SIZE] = { 0 };
size_t len = 0; size_t len = 0;
if (img->fmt == VPX_IMG_FMT_I440 || img->fmt == VPX_IMG_FMT_I44016) { if (img->fmt == VPX_IMG_FMT_I440 || img->fmt == VPX_IMG_FMT_I44016) {
fprintf(stderr, "Cannot produce y4m output for 440 sampling.\n"); fprintf(stderr, "Cannot produce y4m output for 440 sampling.\n");
@ -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;
} }

1101
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,18 +75,17 @@ 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);
} }
} }
void stats_write(stats_io_t *stats, const void *pkt, size_t len) { void stats_write(stats_io_t *stats, const void *pkt, size_t len) {
if (stats->file) { if (stats->file) {
(void) fwrite(pkt, 1, len, stats->file); (void)fwrite(pkt, 1, len, stats->file);
} else { } else {
if (stats->buf.sz + len > stats->buf_alloc_sz) { if (stats->buf.sz + len > stats->buf_alloc_sz) {
size_t new_sz = stats->buf_alloc_sz + 64 * 1024; size_t new_sz = stats->buf_alloc_sz + 64 * 1024;
char *new_ptr = realloc(stats->buf.buf, new_sz); char *new_ptr = realloc(stats->buf.buf, new_sz);
if (new_ptr) { if (new_ptr) {
stats->buf_ptr = new_ptr + (stats->buf_ptr - (char *)stats->buf.buf); stats->buf_ptr = new_ptr + (stats->buf_ptr - (char *)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);
@ -91,27 +88,22 @@ void check_encoder_config(int disable_prompt,
const struct vpx_codec_enc_cfg *stream_config) { const struct vpx_codec_enc_cfg *stream_config) {
int num_warnings = 0; int num_warnings = 0;
struct WarningListNode *warning = NULL; struct WarningListNode *warning = NULL;
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

@ -21,12 +21,12 @@ namespace {
void reset(struct WebmInputContext *const webm_ctx) { void reset(struct WebmInputContext *const webm_ctx) {
if (webm_ctx->reader != NULL) { if (webm_ctx->reader != NULL) {
mkvparser::MkvReader *const reader = mkvparser::MkvReader *const reader =
reinterpret_cast<mkvparser::MkvReader*>(webm_ctx->reader); reinterpret_cast<mkvparser::MkvReader *>(webm_ctx->reader);
delete reader; delete reader;
} }
if (webm_ctx->segment != NULL) { if (webm_ctx->segment != NULL) {
mkvparser::Segment *const segment = mkvparser::Segment *const segment =
reinterpret_cast<mkvparser::Segment*>(webm_ctx->segment); reinterpret_cast<mkvparser::Segment *>(webm_ctx->segment);
delete segment; delete segment;
} }
if (webm_ctx->buffer != NULL) { if (webm_ctx->buffer != NULL) {
@ -46,7 +46,7 @@ void reset(struct WebmInputContext *const webm_ctx) {
void get_first_cluster(struct WebmInputContext *const webm_ctx) { void get_first_cluster(struct WebmInputContext *const webm_ctx) {
mkvparser::Segment *const segment = mkvparser::Segment *const segment =
reinterpret_cast<mkvparser::Segment*>(webm_ctx->segment); reinterpret_cast<mkvparser::Segment *>(webm_ctx->segment);
const mkvparser::Cluster *const cluster = segment->GetFirst(); const mkvparser::Cluster *const cluster = segment->GetFirst();
webm_ctx->cluster = cluster; webm_ctx->cluster = cluster;
} }
@ -72,7 +72,7 @@ int file_is_webm(struct WebmInputContext *webm_ctx,
return 0; return 0;
} }
mkvparser::Segment* segment; mkvparser::Segment *segment;
if (mkvparser::Segment::CreateInstance(reader, pos, segment)) { if (mkvparser::Segment::CreateInstance(reader, pos, segment)) {
rewind_and_reset(webm_ctx, vpx_ctx); rewind_and_reset(webm_ctx, vpx_ctx);
return 0; return 0;
@ -84,11 +84,11 @@ int file_is_webm(struct WebmInputContext *webm_ctx,
} }
const mkvparser::Tracks *const tracks = segment->GetTracks(); const mkvparser::Tracks *const tracks = segment->GetTracks();
const mkvparser::VideoTrack* video_track = NULL; const mkvparser::VideoTrack *video_track = NULL;
for (unsigned long i = 0; i < tracks->GetTracksCount(); ++i) { for (unsigned long i = 0; i < tracks->GetTracksCount(); ++i) {
const mkvparser::Track* const track = tracks->GetTrackByIndex(i); const mkvparser::Track *const track = tracks->GetTrackByIndex(i);
if (track->GetType() == mkvparser::Track::kVideo) { if (track->GetType() == mkvparser::Track::kVideo) {
video_track = static_cast<const mkvparser::VideoTrack*>(track); video_track = static_cast<const mkvparser::VideoTrack *>(track);
webm_ctx->video_track_index = track->GetNumber(); webm_ctx->video_track_index = track->GetNumber();
break; break;
} }
@ -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.
@ -127,13 +126,13 @@ int webm_read_frame(struct WebmInputContext *webm_ctx,
return 1; return 1;
} }
mkvparser::Segment *const segment = mkvparser::Segment *const segment =
reinterpret_cast<mkvparser::Segment*>(webm_ctx->segment); reinterpret_cast<mkvparser::Segment *>(webm_ctx->segment);
const mkvparser::Cluster* cluster = const mkvparser::Cluster *cluster =
reinterpret_cast<const mkvparser::Cluster*>(webm_ctx->cluster); reinterpret_cast<const mkvparser::Cluster *>(webm_ctx->cluster);
const mkvparser::Block *block = const mkvparser::Block *block =
reinterpret_cast<const mkvparser::Block*>(webm_ctx->block); reinterpret_cast<const mkvparser::Block *>(webm_ctx->block);
const mkvparser::BlockEntry *block_entry = const mkvparser::BlockEntry *block_entry =
reinterpret_cast<const mkvparser::BlockEntry*>(webm_ctx->block_entry); reinterpret_cast<const mkvparser::BlockEntry *>(webm_ctx->block_entry);
bool block_entry_eos = false; bool block_entry_eos = false;
do { do {
long status = 0; long status = 0;
@ -175,11 +174,11 @@ int webm_read_frame(struct WebmInputContext *webm_ctx,
webm_ctx->block_entry = block_entry; webm_ctx->block_entry = block_entry;
webm_ctx->block = block; webm_ctx->block = block;
const mkvparser::Block::Frame& frame = const mkvparser::Block::Frame &frame =
block->GetFrame(webm_ctx->block_frame_index); block->GetFrame(webm_ctx->block_frame_index);
++webm_ctx->block_frame_index; ++webm_ctx->block_frame_index;
if (frame.len > static_cast<long>(*buffer_size)) { if (frame.len > static_cast<long>(*buffer_size)) {
delete[] *buffer; delete[] * buffer;
*buffer = new uint8_t[frame.len]; *buffer = new uint8_t[frame.len];
if (*buffer == NULL) { if (*buffer == NULL) {
return -1; return -1;
@ -191,7 +190,7 @@ int webm_read_frame(struct WebmInputContext *webm_ctx,
webm_ctx->is_key_frame = block->IsKey(); webm_ctx->is_key_frame = block->IsKey();
mkvparser::MkvReader *const reader = mkvparser::MkvReader *const reader =
reinterpret_cast<mkvparser::MkvReader*>(webm_ctx->reader); reinterpret_cast<mkvparser::MkvReader *>(webm_ctx->reader);
return frame.Read(reader, *buffer) ? -1 : 0; return frame.Read(reader, *buffer) ? -1 : 0;
} }
@ -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 = segment->GetTrackByNumber(video_track_id));
static_cast<mkvmuxer::VideoTrack*>(
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"; case VP9_FOURCC:
break; default: codec_id = "V_VP9"; break;
case VP9_FOURCC:
default:
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);
} }
@ -80,25 +72,22 @@ void write_webm_block(struct WebmOutputContext *webm_ctx,
const vpx_codec_enc_cfg_t *cfg, const vpx_codec_enc_cfg_t *cfg,
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);
} }
void write_webm_file_footer(struct WebmOutputContext *webm_ctx) { void write_webm_file_footer(struct WebmOutputContext *webm_ctx) {
mkvmuxer::MkvWriter *const writer = mkvmuxer::MkvWriter *const writer =
reinterpret_cast<mkvmuxer::MkvWriter*>(webm_ctx->writer); reinterpret_cast<mkvmuxer::MkvWriter *>(webm_ctx->writer);
mkvmuxer::Segment *const segment = mkvmuxer::Segment *const segment =
reinterpret_cast<mkvmuxer::Segment*>(webm_ctx->segment); reinterpret_cast<mkvmuxer::Segment *>(webm_ctx->segment);
segment->Finalize(); segment->Finalize();
delete segment; delete segment;
delete writer; delete writer;

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

@ -25,7 +25,7 @@ static int file_read(void *buf, size_t size, FILE *file) {
int file_error; int file_error;
size_t len = 0; size_t len = 0;
do { do {
const size_t n = fread((uint8_t*)buf + len, 1, size - len, file); const size_t n = fread((uint8_t *)buf + len, 1, size - len, file);
len += n; len += n;
file_error = ferror(file); file_error = ferror(file);
if (file_error) { if (file_error) {
@ -41,83 +41,77 @@ 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: %d, retries: %d, %d: %s\n", "Error reading file: %u of %u bytes read,"
(uint32_t)len, (uint32_t)size, file_error, retry_count, " error: %d, retries: %d, %d: %s\n",
errno, strerror(errno)); (uint32_t)len, (uint32_t)size, file_error, retry_count, errno,
strerror(errno));
} }
return len == size; return len == size;
} }
static int y4m_parse_tags(y4m_input *_y4m, char *_tags) { static int y4m_parse_tags(y4m_input *_y4m, char *_tags) {
int got_w; int got_w;
int got_h; int got_h;
int got_fps; int got_fps;
int got_interlace; int got_interlace;
int got_par; int got_par;
int got_chroma; int got_chroma;
char *p; char *p;
char *q; char *q;
got_w = got_h = got_fps = got_interlace = got_par = got_chroma = 0; got_w = got_h = got_fps = got_interlace = got_par = got_chroma = 0;
for (p = _tags;; p = q) { for (p = _tags;; p = q) {
/*Skip any leading spaces.*/ /*Skip any leading spaces.*/
while (*p == ' ')p++; while (*p == ' ') p++;
/*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.*/
} }
} }
if (!got_w || !got_h || !got_fps)return -1; if (!got_w || !got_h || !got_fps) return -1;
if (!got_interlace)_y4m->interlace = '?'; if (!got_interlace) _y4m->interlace = '?';
if (!got_par)_y4m->par_n = _y4m->par_d = 0; if (!got_par) _y4m->par_n = _y4m->par_d = 0;
/*Chroma-type is not specified in older files, e.g., those generated by /*Chroma-type is not specified in older files, e.g., those generated by
mplayer.*/ mplayer.*/
if (!got_chroma)strcpy(_y4m->chroma_type, "420"); if (!got_chroma) strcpy(_y4m->chroma_type, "420");
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):
@ -140,9 +134,9 @@ static int y4m_parse_tags(y4m_input *_y4m, char *_tags) {
have these steps pipelined, for less memory consumption and better cache have these steps pipelined, for less memory consumption and better cache
performance, but we do them separately for simplicity.*/ performance, but we do them separately for simplicity.*/
#define OC_MINI(_a,_b) ((_a)>(_b)?(_b):(_a)) #define OC_MINI(_a, _b) ((_a) > (_b) ? (_b) : (_a))
#define OC_MAXI(_a,_b) ((_a)<(_b)?(_b):(_a)) #define OC_MAXI(_a, _b) ((_a) < (_b) ? (_b) : (_a))
#define OC_CLAMPI(_a,_b,_c) (OC_MAXI(_a,OC_MINI(_b,_c))) #define OC_CLAMPI(_a, _b, _c) (OC_MAXI(_a, OC_MINI(_b, _c)))
/*420jpeg chroma samples are sited like: /*420jpeg chroma samples are sited like:
Y-------Y-------Y-------Y------- Y-------Y-------Y-------Y-------
@ -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;
@ -277,12 +282,12 @@ static void y4m_convert_42xmpeg2_42xjpeg(y4m_input *_y4m, unsigned char *_dst,
static void y4m_convert_42xpaldv_42xjpeg(y4m_input *_y4m, unsigned char *_dst, static void y4m_convert_42xpaldv_42xjpeg(y4m_input *_y4m, unsigned char *_dst,
unsigned char *_aux) { unsigned char *_aux) {
unsigned char *tmp; unsigned char *tmp;
int c_w; int c_w;
int c_h; int c_h;
int c_sz; int c_sz;
int pli; int pli;
int y; int y;
int x; int x;
/*Skip past the luma data.*/ /*Skip past the luma data.*/
_dst += _y4m->pic_w * _y4m->pic_h; _dst += _y4m->pic_w * _y4m->pic_h;
/*Compute the size of each chroma plane.*/ /*Compute the size of each chroma plane.*/
@ -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++;
@ -496,12 +531,12 @@ static void y4m_convert_422jpeg_420jpeg(y4m_input *_y4m, unsigned char *_dst,
static void y4m_convert_422_420jpeg(y4m_input *_y4m, unsigned char *_dst, static void y4m_convert_422_420jpeg(y4m_input *_y4m, unsigned char *_dst,
unsigned char *_aux) { unsigned char *_aux) {
unsigned char *tmp; unsigned char *tmp;
int c_w; int c_w;
int c_h; int c_h;
int c_sz; int c_sz;
int dst_c_h; int dst_c_h;
int dst_c_sz; int dst_c_sz;
int pli; int pli;
/*Skip past the luma data.*/ /*Skip past the luma data.*/
_dst += _y4m->pic_w * _y4m->pic_h; _dst += _y4m->pic_w * _y4m->pic_h;
/*Compute the size of each chroma plane.*/ /*Compute the size of each chroma plane.*/
@ -568,16 +603,16 @@ static void y4m_convert_422_420jpeg(y4m_input *_y4m, unsigned char *_dst,
static void y4m_convert_411_420jpeg(y4m_input *_y4m, unsigned char *_dst, static void y4m_convert_411_420jpeg(y4m_input *_y4m, unsigned char *_dst,
unsigned char *_aux) { unsigned char *_aux) {
unsigned char *tmp; unsigned char *tmp;
int c_w; int c_w;
int c_h; int c_h;
int c_sz; int c_sz;
int dst_c_w; int dst_c_w;
int dst_c_h; int dst_c_h;
int dst_c_sz; int dst_c_sz;
int tmp_sz; int tmp_sz;
int pli; int pli;
int y; int y;
int x; int x;
/*Skip past the luma data.*/ /*Skip past the luma data.*/
_dst += _y4m->pic_w * _y4m->pic_h; _dst += _y4m->pic_w * _y4m->pic_h;
/*Compute the size of each chroma plane.*/ /*Compute the size of each chroma plane.*/
@ -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;
@ -631,16 +685,16 @@ static void y4m_convert_411_420jpeg(y4m_input *_y4m, unsigned char *_dst,
static void y4m_convert_444_420jpeg(y4m_input *_y4m, unsigned char *_dst, static void y4m_convert_444_420jpeg(y4m_input *_y4m, unsigned char *_dst,
unsigned char *_aux) { unsigned char *_aux) {
unsigned char *tmp; unsigned char *tmp;
int c_w; int c_w;
int c_h; int c_h;
int c_sz; int c_sz;
int dst_c_w; int dst_c_w;
int dst_c_h; int dst_c_h;
int dst_c_sz; int dst_c_sz;
int tmp_sz; int tmp_sz;
int pli; int pli;
int y; int y;
int x; int x;
/*Skip past the luma data.*/ /*Skip past the luma data.*/
_dst += _y4m->pic_w * _y4m->pic_h; _dst += _y4m->pic_w * _y4m->pic_h;
/*Compute the size of each chroma plane.*/ /*Compute the size of each chroma plane.*/
@ -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(
17 * (_aux[x - 1] + _aux[OC_MINI(x + 2, c_w - 1)]) + 0, (3 * (_aux[x - 2] + _aux[c_w - 1]) -
78 * (_aux[x] + _aux[OC_MINI(x + 1, c_w - 1)]) + 64) >> 7, 255); 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);
} }
tmp += dst_c_w; tmp += dst_c_w;
_aux += c_w; _aux += c_w;
@ -700,9 +763,9 @@ static void y4m_convert_null(y4m_input *_y4m, unsigned char *_dst,
int y4m_input_open(y4m_input *_y4m, FILE *_fin, char *_skip, int _nskip, int y4m_input_open(y4m_input *_y4m, FILE *_fin, char *_skip, int _nskip,
int only_420) { int only_420) {
char buffer[80] = {0}; char buffer[80] = { 0 };
int ret; int ret;
int i; int i;
/*Read until newline, or 80 cols, whichever happens first.*/ /*Read until newline, or 80 cols, whichever happens first.*/
for (i = 0; i < 79; i++) { for (i = 0; i < 79; i++) {
if (_nskip > 0) { if (_nskip > 0) {
@ -711,10 +774,10 @@ int y4m_input_open(y4m_input *_y4m, FILE *_fin, char *_skip, int _nskip,
} else { } else {
if (!file_read(buffer + i, 1, _fin)) return -1; if (!file_read(buffer + i, 1, _fin)) return -1;
} }
if (buffer[i] == '\n')break; if (buffer[i] == '\n') break;
} }
/*We skipped too much header data.*/ /*We skipped too much header data.*/
if (_nskip > 0)return -1; if (_nskip > 0) return -1;
if (i == 79) { if (i == 79) {
fprintf(stderr, "Error parsing header; not a YUV2MPEG2 file?\n"); fprintf(stderr, "Error parsing header; not a YUV2MPEG2 file?\n");
return -1; return -1;
@ -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,9 +1043,10 @@ 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 +
((_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v); 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);
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);
else else
@ -991,11 +1064,11 @@ void y4m_input_close(y4m_input *_y4m) {
int y4m_input_fetch_frame(y4m_input *_y4m, FILE *_fin, vpx_image_t *_img) { int y4m_input_fetch_frame(y4m_input *_y4m, FILE *_fin, vpx_image_t *_img) {
char frame[6]; char frame[6];
int pic_sz; int pic_sz;
int c_w; int c_w;
int c_h; int c_h;
int c_sz; int c_sz;
int bytes_per_sample = _y4m->bit_depth > 8 ? 2 : 1; int bytes_per_sample = _y4m->bit_depth > 8 ? 2 : 1;
/*Read and skip the frame header.*/ /*Read and skip the frame header.*/
if (!file_read(frame, 6, _fin)) return 0; if (!file_read(frame, 6, _fin)) return 0;
if (memcmp(frame, "FRAME", 5)) { if (memcmp(frame, "FRAME", 5)) {
@ -1004,8 +1077,9 @@ 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

@ -14,52 +14,46 @@
#ifndef Y4MINPUT_H_ #ifndef Y4MINPUT_H_
#define Y4MINPUT_H_ #define Y4MINPUT_H_
# include <stdio.h> #include <stdio.h>
# include "vpx/vpx_image.h" #include "vpx/vpx_image.h"
#ifdef __cplusplus #ifdef __cplusplus
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;
int pic_h; int pic_h;
int fps_n; int fps_n;
int fps_d; int fps_d;
int par_n; int par_n;
int par_d; int par_d;
char interlace; char interlace;
int src_c_dec_h; int src_c_dec_h;
int src_c_dec_v; int src_c_dec_v;
int dst_c_dec_h; int dst_c_dec_h;
int dst_c_dec_v; int dst_c_dec_v;
char chroma_type[16]; char chroma_type[16];
/*The size of each converted frame buffer.*/ /*The size of each converted frame buffer.*/
size_t dst_buf_sz; size_t dst_buf_sz;
/*The amount to read directly into the converted frame buffer.*/ /*The amount to read directly into the converted frame buffer.*/
size_t dst_buf_read_sz; size_t dst_buf_read_sz;
/*The size of the auxilliary buffer.*/ /*The size of the auxilliary buffer.*/
size_t aux_buf_sz; size_t aux_buf_sz;
/*The amount to read into the auxilliary buffer.*/ /*The amount to read into the auxilliary buffer.*/
size_t aux_buf_read_sz; size_t aux_buf_read_sz;
y4m_convert_func convert; y4m_convert_func convert;
unsigned char *dst_buf; unsigned char *dst_buf;
unsigned char *aux_buf; unsigned char *aux_buf;
enum vpx_img_fmt vpx_fmt; enum vpx_img_fmt vpx_fmt;
int bps; int bps;
unsigned int bit_depth; unsigned int bit_depth;
}; };
int y4m_input_open(y4m_input *_y4m, FILE *_fin, char *_skip, int _nskip, int y4m_input_open(y4m_input *_y4m, FILE *_fin, char *_skip, int _nskip,