shithub: dav1d

Download patch

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);