Don't exit on decode errors in vpxenc.
Allows the user to specify whether decode errors should be fatal or not. Also makes mismatches optionally fatal. Change-Id: I58cff4a82f3d42f5653b91cf348a7f669377e632
This commit is contained in:
Родитель
8c16dee4f2
Коммит
9837bf4d40
89
vpxenc.c
89
vpxenc.c
|
@ -139,10 +139,8 @@ void warn(const char *fmt, ...) {
|
|||
}
|
||||
|
||||
|
||||
static void ctx_exit_on_error(vpx_codec_ctx_t *ctx, const char *s, ...) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, s);
|
||||
static void warn_or_exit_on_errorv(vpx_codec_ctx_t *ctx, int fatal,
|
||||
const char *s, va_list ap) {
|
||||
if (ctx->err) {
|
||||
const char *detail = vpx_codec_error_detail(ctx);
|
||||
|
||||
|
@ -152,10 +150,28 @@ static void ctx_exit_on_error(vpx_codec_ctx_t *ctx, const char *s, ...) {
|
|||
if (detail)
|
||||
fprintf(stderr, " %s\n", detail);
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
if (fatal)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
static void ctx_exit_on_error(vpx_codec_ctx_t *ctx, const char *s, ...) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, s);
|
||||
warn_or_exit_on_errorv(ctx, 1, s, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
static void warn_or_exit_on_error(vpx_codec_ctx_t *ctx, int fatal,
|
||||
const char *s, ...) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, s);
|
||||
warn_or_exit_on_errorv(ctx, fatal, s, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/* This structure is used to abstract the different ways of handling
|
||||
* first pass statistics.
|
||||
*/
|
||||
|
@ -950,8 +966,20 @@ static const arg_def_t verbosearg = ARG_DEF("v", "verbose", 0,
|
|||
"Show encoder parameters");
|
||||
static const arg_def_t psnrarg = ARG_DEF(NULL, "psnr", 0,
|
||||
"Show PSNR in status line");
|
||||
static const arg_def_t recontest = ARG_DEF(NULL, "test-decode", 0,
|
||||
"Test encode/decode mismatch");
|
||||
enum TestDecodeFatality {
|
||||
TEST_DECODE_OFF,
|
||||
TEST_DECODE_FATAL,
|
||||
TEST_DECODE_WARN,
|
||||
};
|
||||
static const struct arg_enum_list test_decode_enum[] = {
|
||||
{"off", TEST_DECODE_OFF},
|
||||
{"fatal", TEST_DECODE_FATAL},
|
||||
{"warn", TEST_DECODE_WARN},
|
||||
{NULL, 0}
|
||||
};
|
||||
static const arg_def_t recontest = ARG_DEF_ENUM(NULL, "test-decode", 1,
|
||||
"Test encode/decode mismatch",
|
||||
test_decode_enum);
|
||||
static const arg_def_t framerate = ARG_DEF(NULL, "fps", 1,
|
||||
"Stream frame rate (rate/scale)");
|
||||
static const arg_def_t use_ivf = ARG_DEF(NULL, "ivf", 0,
|
||||
|
@ -1573,7 +1601,7 @@ struct global_config {
|
|||
int limit;
|
||||
int skip_frames;
|
||||
int show_psnr;
|
||||
int test_decode;
|
||||
enum TestDecodeFatality test_decode;
|
||||
int have_framerate;
|
||||
struct vpx_rational framerate;
|
||||
int out_part;
|
||||
|
@ -1698,7 +1726,7 @@ static void parse_global_config(struct global_config *global, char **argv) {
|
|||
else if (arg_match(&arg, &psnrarg, argi))
|
||||
global->show_psnr = 1;
|
||||
else if (arg_match(&arg, &recontest, argi))
|
||||
global->test_decode = 1;
|
||||
global->test_decode = arg_parse_enum_or_int(&arg);
|
||||
else if (arg_match(&arg, &framerate, argi)) {
|
||||
global->framerate = arg_parse_rational(&arg);
|
||||
validate_positive_rational(arg.name, &global->framerate);
|
||||
|
@ -2200,7 +2228,7 @@ static void initialize_encoder(struct stream_state *stream,
|
|||
}
|
||||
|
||||
#if CONFIG_DECODERS
|
||||
if (global->test_decode) {
|
||||
if (global->test_decode != TEST_DECODE_OFF) {
|
||||
int width, height;
|
||||
|
||||
vpx_codec_dec_init(&stream->decoder, global->codec->dx_iface(), NULL, 0);
|
||||
|
@ -2303,10 +2331,16 @@ static void get_cx_data(struct stream_state *stream,
|
|||
|
||||
*got_data = 1;
|
||||
#if CONFIG_DECODERS
|
||||
if (global->test_decode) {
|
||||
if (global->test_decode != TEST_DECODE_OFF && !stream->mismatch_seen) {
|
||||
vpx_codec_decode(&stream->decoder, pkt->data.frame.buf,
|
||||
pkt->data.frame.sz, NULL, 0);
|
||||
ctx_exit_on_error(&stream->decoder, "Failed to decode frame");
|
||||
if (stream->decoder.err) {
|
||||
warn_or_exit_on_error(&stream->decoder,
|
||||
global->test_decode == TEST_DECODE_FATAL,
|
||||
"Failed to decode frame %d in stream %d",
|
||||
stream->frames_out + 1, stream->index);
|
||||
stream->mismatch_seen = stream->frames_out + 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
@ -2362,22 +2396,25 @@ static float usec_to_fps(uint64_t usec, unsigned int frames) {
|
|||
}
|
||||
|
||||
|
||||
static void test_decode(struct stream_state *stream) {
|
||||
static void test_decode(struct stream_state *stream,
|
||||
enum TestDecodeFatality fatal) {
|
||||
if (stream->mismatch_seen)
|
||||
return;
|
||||
|
||||
vpx_codec_control(&stream->encoder, VP8_COPY_REFERENCE, &stream->ref_enc);
|
||||
ctx_exit_on_error(&stream->encoder, "Failed to get encoder reference frame");
|
||||
vpx_codec_control(&stream->decoder, VP8_COPY_REFERENCE, &stream->ref_dec);
|
||||
ctx_exit_on_error(&stream->decoder, "Failed to get decoder reference frame");
|
||||
|
||||
if (!stream->mismatch_seen
|
||||
&& !compare_img(&stream->ref_enc.img, &stream->ref_dec.img)) {
|
||||
/* TODO(jkoleszar): make fatal. */
|
||||
if (!compare_img(&stream->ref_enc.img, &stream->ref_dec.img)) {
|
||||
int y[2], u[2], v[2];
|
||||
find_mismatch(&stream->ref_enc.img, &stream->ref_dec.img,
|
||||
y, u, v);
|
||||
warn("Stream %d: Encode/decode mismatch on frame %d"
|
||||
" at Y[%d, %d], U[%d, %d], V[%d, %d]",
|
||||
stream->index, stream->frames_out,
|
||||
y[0], y[1], u[0], u[1], v[0], v[1]);
|
||||
warn_or_exit_on_error(&stream->decoder, fatal == TEST_DECODE_FATAL,
|
||||
"Stream %d: Encode/decode mismatch on frame %d"
|
||||
" at Y[%d, %d], U[%d, %d], V[%d, %d]",
|
||||
stream->index, stream->frames_out,
|
||||
y[0], y[1], u[0], u[1], v[0], v[1]);
|
||||
stream->mismatch_seen = stream->frames_out;
|
||||
}
|
||||
}
|
||||
|
@ -2411,6 +2448,7 @@ int main(int argc, const char **argv_) {
|
|||
char **argv, **argi;
|
||||
unsigned long cx_time = 0;
|
||||
int stream_cnt = 0;
|
||||
int res = 0;
|
||||
|
||||
exec_name = argv_[0];
|
||||
|
||||
|
@ -2596,8 +2634,8 @@ int main(int argc, const char **argv_) {
|
|||
estimated_time_left = average_rate ? remaining / average_rate : -1;
|
||||
}
|
||||
|
||||
if (got_data && global.test_decode)
|
||||
FOREACH_STREAM(test_decode(stream));
|
||||
if (got_data && global.test_decode != TEST_DECODE_OFF)
|
||||
FOREACH_STREAM(test_decode(stream, global.test_decode));
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
|
@ -2627,7 +2665,7 @@ int main(int argc, const char **argv_) {
|
|||
|
||||
FOREACH_STREAM(vpx_codec_destroy(&stream->encoder));
|
||||
|
||||
if (global.test_decode) {
|
||||
if (global.test_decode != TEST_DECODE_OFF) {
|
||||
FOREACH_STREAM(vpx_codec_destroy(&stream->decoder));
|
||||
FOREACH_STREAM(vpx_img_free(&stream->ref_enc.img));
|
||||
FOREACH_STREAM(vpx_img_free(&stream->ref_dec.img));
|
||||
|
@ -2635,6 +2673,9 @@ int main(int argc, const char **argv_) {
|
|||
|
||||
close_input_file(&input);
|
||||
|
||||
if (global.test_decode == TEST_DECODE_FATAL) {
|
||||
FOREACH_STREAM(res |= stream->mismatch_seen);
|
||||
}
|
||||
FOREACH_STREAM(close_output_file(stream, global.codec->fourcc));
|
||||
|
||||
FOREACH_STREAM(stats_close(&stream->stats, global.passes - 1));
|
||||
|
@ -2672,5 +2713,5 @@ int main(int argc, const char **argv_) {
|
|||
vpx_img_free(&raw);
|
||||
free(argv);
|
||||
free(streams);
|
||||
return EXIT_SUCCESS;
|
||||
return res ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче