ref: 046188e48787b74717d921c58c46371ff2d00ea1
parent: ed35b5bac082b8dd9f1bf308c8eb32c5054a6dfa
author: Henrik Gramner <gramner@twoorioles.com>
date: Fri May 10 19:00:15 EDT 2019
Add an option to limit the maximum frame size
--- a/include/dav1d/dav1d.h
+++ b/include/dav1d/dav1d.h
@@ -64,6 +64,7 @@
int apply_grain;
int operating_point; ///< select an operating point for scalable AV1 bitstreams (0 - 31)
int all_layers; ///< output all spatial layers of a scalable AV1 biststream
+ unsigned frame_size_limit; ///< maximum frame size, in pixels (0 = unlimited)
Dav1dPicAllocator allocator;
Dav1dLogger logger;
} Dav1dSettings;
--- a/meson.build
+++ b/meson.build
@@ -30,7 +30,7 @@
'b_ndebug=if-release'],
meson_version: '>= 0.47.0')
-dav1d_soname_version = '1.1.0'
+dav1d_soname_version = '2.0.0'
dav1d_api_version_array = dav1d_soname_version.split('.')
dav1d_api_version_major = dav1d_api_version_array[0]
dav1d_api_version_minor = dav1d_api_version_array[1]
--- a/src/internal.h
+++ b/src/internal.h
@@ -127,6 +127,7 @@
int operating_point;
unsigned operating_point_idc;
int all_layers;
+ unsigned frame_size_limit;
int drain;
Dav1dLogger logger;
--- a/src/lib.c
+++ b/src/lib.c
@@ -67,6 +67,7 @@
s->logger.callback = dav1d_log_default_callback;
s->operating_point = 0;
s->all_layers = 1; // just until the tests are adjusted
+ s->frame_size_limit = 0;
}
static void close_internal(Dav1dContext **const c_out, int flush);
@@ -101,6 +102,7 @@
c->apply_grain = s->apply_grain;
c->operating_point = s->operating_point;
c->all_layers = s->all_layers;
+ c->frame_size_limit = s->frame_size_limit;
c->frame_thread.flush = &c->frame_thread.flush_mem;
atomic_init(c->frame_thread.flush, 0);
c->n_fc = s->n_frame_threads;
--- a/src/obu.c
+++ b/src/obu.c
@@ -1306,6 +1306,15 @@
goto error;
}
+ if (c->frame_size_limit && (int64_t)c->frame_hdr->width[1] *
+ c->frame_hdr->height > c->frame_size_limit)
+ {
+ dav1d_log(c, "Frame size %dx%d exceeds limit %u\n", c->frame_hdr->width[1],
+ c->frame_hdr->height, c->frame_size_limit);
+ c->frame_hdr = NULL;
+ return DAV1D_ERR(ERANGE);
+ }
+
// This is the frame header at the start of a frame OBU.
// There's no trailing bit at the end to skip, but we do need
// to align to the next byte.
--- a/tools/dav1d_cli_parse.c
+++ b/tools/dav1d_cli_parse.c
@@ -29,6 +29,7 @@
#include <assert.h>
#include <getopt.h>
+#include <limits.h>
#include <math.h>
#include <stdarg.h>
#include <stdio.h>
@@ -55,6 +56,7 @@
ARG_FILM_GRAIN,
ARG_OPPOINT,
ARG_ALL_LAYERS,
+ ARG_SIZE_LIMIT,
ARG_CPU_MASK,
};
@@ -76,6 +78,7 @@
{ "filmgrain", 1, NULL, ARG_FILM_GRAIN },
{ "oppoint", 1, NULL, ARG_OPPOINT },
{ "alllayers", 1, NULL, ARG_ALL_LAYERS },
+ { "sizelimit", 1, NULL, ARG_SIZE_LIMIT },
{ "cpumask", 1, NULL, ARG_CPU_MASK },
{ NULL, 0, NULL, 0 },
};
@@ -116,6 +119,7 @@
" --filmgrain $num: enable film grain application (default: 1, except if muxer is md5)\n"
" --oppoint $num: select an operating point of a scalable AV1 bitstream (0 - 32)\n"
" --alllayers $num: output all spatial layers of a scalable AV1 bitstream (default: 1)\n"
+ " --sizelimit $num: stop decoding if the frame size exceeds the specified limit\n"
" --verify $md5: verify decoded md5. implies --muxer md5, no output\n"
" --cpumask $mask: restrict permitted CPU instruction sets (0" ALLOWED_CPU_MASKS "; default: -1)\n");
exit(1);
@@ -308,6 +312,17 @@
lib_settings->all_layers =
!!parse_unsigned(optarg, ARG_ALL_LAYERS, argv[0]);
break;
+ case ARG_SIZE_LIMIT:
+ {
+ char *arg = optarg, *end;
+ uint64_t res = strtoul(arg, &end, 0);
+ if (*end == 'x') // NxM
+ res *= strtoul((arg = end + 1), &end, 0);
+ if (*end || end == arg || res >= UINT_MAX)
+ error(argv[0], optarg, ARG_SIZE_LIMIT, "an integer or dimension");
+ lib_settings->frame_size_limit = (unsigned) res;
+ break;
+ }
case 'v':
fprintf(stderr, "%s\n", dav1d_version());
exit(0);