Commit 6fd4013a authored by Janne Grunau's avatar Janne Grunau Committed by Jean-Baptiste Kempf

dav1d: add --verify option to verify decoding results

Will be used for regression tests.
parent 285d1b76
......@@ -167,7 +167,10 @@ int main(const int argc, char *const *const argv) {
if (out) {
if (!cli_settings.quiet && istty)
fprintf(stderr, "\n");
output_close(out);
if (cli_settings.verify)
res |= output_verify(out, cli_settings.verify);
else
output_close(out);
} else {
fprintf(stderr, "No data decoded\n");
res = 1;
......
......@@ -47,6 +47,7 @@ enum {
ARG_MUXER,
ARG_FRAME_THREADS,
ARG_TILE_THREADS,
ARG_VERIFY,
};
static const struct option long_opts[] = {
......@@ -60,6 +61,7 @@ static const struct option long_opts[] = {
{ "skip", 1, NULL, 's' },
{ "framethreads", 1, NULL, ARG_FRAME_THREADS },
{ "tilethreads", 1, NULL, ARG_TILE_THREADS },
{ "verify", 1, NULL, ARG_VERIFY },
{ NULL, 0, NULL, 0 },
};
......@@ -83,7 +85,8 @@ static void usage(const char *const app, const char *const reason, ...) {
" --skip/-s $num: skip decoding of the first $num frames\n"
" --version/-v: print version and exit\n"
" --framethreads $num: number of frame threads (default: 1)\n"
" --tilethreads $num: number of tile threads (default: 1)\n");
" --tilethreads $num: number of tile threads (default: 1)\n"
" --verify $md5: verify decoded md5. implies --muxer md5, no output\n");
exit(1);
}
......@@ -153,6 +156,9 @@ void parse(const int argc, char *const *const argv,
lib_settings->n_tile_threads =
parse_unsigned(optarg, ARG_TILE_THREADS, argv[0]);
break;
case ARG_VERIFY:
cli_settings->verify = optarg;
break;
case 'v':
fprintf(stderr, "%s\n", dav1d_version());
exit(0);
......@@ -161,6 +167,17 @@ void parse(const int argc, char *const *const argv,
}
}
if (cli_settings->verify) {
if (cli_settings->outputfile)
usage(argv[0], "Verification (--verify) requires output file (-o/--output) to not set");
if (cli_settings->muxer && !strcmp(cli_settings->muxer, "md5"))
usage(argv[0], "Verification (--verify) requires the md5 muxer (--muxer md5)");
cli_settings->outputfile = "-";
if (!cli_settings->muxer)
cli_settings->muxer = "md5";
}
if (!cli_settings->inputfile)
usage(argv[0], "Input file (-i/--input) is required");
if (!cli_settings->outputfile)
......
......@@ -35,6 +35,7 @@ typedef struct {
const char *inputfile;
const char *demuxer;
const char *muxer;
const char *verify;
unsigned limit, skip;
int quiet;
} CLISettings;
......
......@@ -190,7 +190,7 @@ static int md5_write(MD5Context *const md5, Dav1dPicture *const p) {
return 0;
}
static void md5_close(MD5Context *const md5) {
static void md5_finish(MD5Context *const md5) {
static const uint8_t bit[2] = { 0x80, 0x00 };
uint64_t len = md5->len << 3;
......@@ -198,6 +198,10 @@ static void md5_close(MD5Context *const md5) {
while ((md5->len & 63) != 56)
md5_update(md5, &bit[1], 1);
md5_update(md5, (uint8_t *) &len, 8);
}
static void md5_close(MD5Context *const md5) {
md5_finish(md5);
for (int i = 0; i < 4; i++)
fprintf(md5->f, "%2.2x%2.2x%2.2x%2.2x",
md5->abcd[i] & 0xff,
......@@ -210,6 +214,29 @@ static void md5_close(MD5Context *const md5) {
fclose(md5->f);
}
static int md5_verify(MD5Context *const md5, const char *const md5_str) {
md5_finish(md5);
if (strlen(md5_str) < 32)
return 0;
const char *p = md5_str;
unsigned abcd[4] = { 0 };
char t[3] = { 0 };
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
unsigned val;
char *ignore;
memcpy(t, p, 2);
p += 2;
val = strtoul(t, &ignore, 16);
abcd[i] |= val << (8 * j);
}
}
return memcmp(abcd, md5->abcd, sizeof(abcd));
}
const Muxer md5_muxer = {
.priv_data_size = sizeof(MD5Context),
.name = "md5",
......@@ -217,4 +244,5 @@ const Muxer md5_muxer = {
.write_header = md5_open,
.write_picture = md5_write,
.write_trailer = md5_close,
.verify = md5_verify,
};
......@@ -39,6 +39,14 @@ typedef struct Muxer {
const Dav1dPictureParameters *p, const unsigned fps[2]);
int (*write_picture)(MuxerPriv *ctx, Dav1dPicture *p);
void (*write_trailer)(MuxerPriv *ctx);
/**
* Verifies the muxed data (for example in the md5 muxer). Replaces write_trailer.
*
* @param hash_string Muxer specific reference value.
*
* @return 0 on success.
*/
int (*verify)(MuxerPriv *ctx, const char *hash_string);
} Muxer;
#endif /* __DAV1D_OUTPUT_MUXER_H__ */
......@@ -142,3 +142,11 @@ void output_close(MuxerContext *const ctx) {
ctx->impl->write_trailer(ctx->data);
free(ctx);
}
int output_verify(MuxerContext *const ctx, const char *const md5_Str) {
int res = 0;
if (ctx->impl->verify)
res = ctx->impl->verify(ctx->data, md5_Str);
free(ctx);
return res;
}
......@@ -37,5 +37,13 @@ int output_open(MuxerContext **c, const char *name, const char *filename,
const Dav1dPictureParameters *p, const unsigned fps[2]);
int output_write(MuxerContext *ctx, Dav1dPicture *pic);
void output_close(MuxerContext *ctx);
/**
* Verifies the muxed data (for example in the md5 muxer). Replaces output_close.
*
* @param hash_string Muxer specific reference value.
*
* @return 0 on success.
*/
int output_verify(MuxerContext *ctx, const char *hash_string);
#endif /* __DAV1D_OUTPUT_OUTPUT_H__ */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment