Commit b6d8436f authored by Ronald S. Bultje's avatar Ronald S. Bultje

add --inloopfilters to enable/disable postfilters dynamically

(To be used alongside --filmgrain.)

Addresses part of #310.
parent 650cb151
Pipeline #12242 passed with stages
in 8 minutes and 41 seconds
......@@ -66,7 +66,16 @@ typedef struct Dav1dSettings {
int all_layers; ///< output all spatial layers of a scalable AV1 biststream
unsigned frame_size_limit; ///< maximum frame size, in pixels (0 = unlimited)
int output_invisible_frames;
uint8_t reserved[28]; ///< reserved for future use
enum Dav1dInloopFilterType {
DAV1D_INLOOPFILTER_NONE = 0,
DAV1D_INLOOPFILTER_DEBLOCK = 1 << 0,
DAV1D_INLOOPFILTER_CDEF = 1 << 1,
DAV1D_INLOOPFILTER_RESTORATION = 1 << 2,
DAV1D_INLOOPFILTER_ALL = DAV1D_INLOOPFILTER_DEBLOCK |
DAV1D_INLOOPFILTER_CDEF |
DAV1D_INLOOPFILTER_RESTORATION,
} inloop_filters;
uint8_t reserved[24]; ///< reserved for future use
Dav1dPicAllocator allocator;
Dav1dLogger logger;
} Dav1dSettings;
......
......@@ -133,6 +133,7 @@ struct Dav1dContext {
int all_layers;
unsigned frame_size_limit;
int output_invisible_frames;
enum Dav1dInloopFilterType inloop_filters;
int drain;
Dav1dLogger logger;
......
......@@ -76,6 +76,7 @@ COLD void dav1d_default_settings(Dav1dSettings *const s) {
s->all_layers = 1; // just until the tests are adjusted
s->frame_size_limit = 0;
s->output_invisible_frames = 0;
s->inloop_filters = DAV1D_INLOOPFILTER_ALL;
}
static void close_internal(Dav1dContext **const c_out, int flush);
......@@ -124,6 +125,7 @@ COLD int dav1d_open(Dav1dContext **const c_out, const Dav1dSettings *const s) {
c->all_layers = s->all_layers;
c->frame_size_limit = s->frame_size_limit;
c->output_invisible_frames = s->output_invisible_frames;
c->inloop_filters = s->inloop_filters;
/* On 32-bit systems extremely large frame sizes can cause overflows in
* dav1d_decode_frame() malloc size calculations. Prevent that from occuring
......
......@@ -1966,10 +1966,11 @@ int bytefn(dav1d_recon_b_inter)(Dav1dTileContext *const t, const enum BlockSize
}
void bytefn(dav1d_filter_sbrow)(Dav1dFrameContext *const f, const int sby) {
const Dav1dContext *const c = f->c;
const int sbsz = f->sb_step, sbh = f->sbh;
if (f->frame_hdr->loopfilter.level_y[0] ||
f->frame_hdr->loopfilter.level_y[1])
if (c->inloop_filters & DAV1D_INLOOPFILTER_DEBLOCK &&
(f->frame_hdr->loopfilter.level_y[0] || f->frame_hdr->loopfilter.level_y[1]))
{
int start_of_tile_row = 0;
if (f->frame_hdr->tiling.row_start_sb[f->lf.tile_row] == sby)
......@@ -1982,7 +1983,7 @@ void bytefn(dav1d_filter_sbrow)(Dav1dFrameContext *const f, const int sby) {
// Store loop filtered pixels required by loop restoration
bytefn(dav1d_lr_copy_lpf)(f, f->lf.p, sby);
}
if (f->seq_hdr->cdef) {
if (c->inloop_filters & DAV1D_INLOOPFILTER_CDEF && f->seq_hdr->cdef) {
if (sby) {
const int ss_ver = f->cur.p.layout == DAV1D_PIXEL_LAYOUT_I420;
pixel *p_up[3] = {
......@@ -2017,7 +2018,7 @@ void bytefn(dav1d_filter_sbrow)(Dav1dFrameContext *const f, const int sby) {
f->resize_start[!!pl] HIGHBD_CALL_SUFFIX);
}
}
if (f->lf.restore_planes) {
if (c->inloop_filters & DAV1D_INLOOPFILTER_RESTORATION && f->lf.restore_planes) {
bytefn(dav1d_lr_sbrow)(f, f->lf.sr_p, sby);
}
......
......@@ -58,6 +58,7 @@ enum {
ARG_SIZE_LIMIT,
ARG_CPU_MASK,
ARG_OUTPUT_INVISIBLE,
ARG_INLOOP_FILTERS,
};
static const struct option long_opts[] = {
......@@ -81,6 +82,7 @@ static const struct option long_opts[] = {
{ "sizelimit", 1, NULL, ARG_SIZE_LIMIT },
{ "cpumask", 1, NULL, ARG_CPU_MASK },
{ "outputinvisible", 1, NULL, ARG_OUTPUT_INVISIBLE },
{ "inloopfilters", 1, NULL, ARG_INLOOP_FILTERS },
{ NULL, 0, NULL, 0 },
};
......@@ -124,7 +126,8 @@ static void usage(const char *const app, const char *const reason, ...) {
" --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"
" --outputinvisible $num: whether to output invisible (alt-ref) frames (default: 0)\n");
" --outputinvisible $num: whether to output invisible (alt-ref) frames (default: 0)\n"
" --inloopfilters $list: which in-loop filters to enable (can be of none, (no)deblock, (no)cdef, (no)restoration or all; default: all)\n");
exit(1);
}
......@@ -201,6 +204,18 @@ static const EnumParseTable cpu_mask_tbl[] = {
{ 0 },
};
static const EnumParseTable inloop_filters_tbl[] = {
{ "none", DAV1D_INLOOPFILTER_NONE },
{ "deblock", DAV1D_INLOOPFILTER_DEBLOCK },
{ "nodeblock", DAV1D_INLOOPFILTER_ALL - DAV1D_INLOOPFILTER_DEBLOCK },
{ "cdef", DAV1D_INLOOPFILTER_CDEF },
{ "nocdef", DAV1D_INLOOPFILTER_ALL - DAV1D_INLOOPFILTER_CDEF },
{ "restoration", DAV1D_INLOOPFILTER_RESTORATION },
{ "norestoration", DAV1D_INLOOPFILTER_ALL - DAV1D_INLOOPFILTER_RESTORATION },
{ "all", DAV1D_INLOOPFILTER_ALL },
{ 0 },
};
static unsigned parse_enum(char *optarg, const EnumParseTable *const tbl,
const int option, const char *app)
{
......@@ -332,6 +347,10 @@ void parse(const int argc, char *const *const argv,
lib_settings->output_invisible_frames =
!!parse_unsigned(optarg, ARG_OUTPUT_INVISIBLE, argv[0]);
break;
case ARG_INLOOP_FILTERS:
lib_settings->inloop_filters =
parse_enum(optarg, inloop_filters_tbl, ARG_INLOOP_FILTERS, argv[0]);
break;
default:
usage(argv[0], NULL);
}
......
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