diff options
author | Niklas Haas <git@haasn.dev> | 2021-09-13 18:57:37 +0300 |
---|---|---|
committer | Niklas Haas <git@haasn.dev> | 2022-01-01 19:23:28 +0300 |
commit | 2a1839451135c71d9c2c96b0c1012ab8ab31fe11 (patch) | |
tree | be345ccf8ab5476a110b778a457085f797c0fbc3 /src/lib.c | |
parent | 3e5b7d377037888ef4c74fe268f71f6b935124ab (diff) |
Expose dav1d_apply_grain as part of the public API
This change is motivated by a desire to be able to toggle between CPU
and GPU film gain synthesis in players such as VLC. Because VLC
initializes the codec before the vout (and, indeed, the active vout
module may change in the middle of decoding), it cannot make the
decision of whether to apply film grain in libdav1d as part of codec
initialization. It needs to be decided on a frame-by-frame basis
depending on whether the currently active vout supports film grain
synthesis or not.
Using the new API, users like VLC can simply set `apply_grain` to 0 and
then manually call `dav1d_apply_grain` whenever the vout does not
support GPU film grain synthesis. As a side note, `dav1d_apply_grain`
could also technically be called from dedicated worker threads,
something that libdav1d does not currently do internally.
The alternative to this solution would have been to allow changing
Dav1dSettings at runtime, but that would be more invasive and a proper
API would also need to take other settings into consideration, some of
which can't be changed as easily as `apply_grain`. This commit
represents a stop-gap solution.
Bump the minor version to allow clients to depend on this API.
Diffstat (limited to 'src/lib.c')
-rw-r--r-- | src/lib.c | 78 |
1 files changed, 47 insertions, 31 deletions
@@ -290,45 +290,24 @@ error: return res; } +static int has_grain(const Dav1dPicture *const pic) +{ + const Dav1dFilmGrainData *fgdata = &pic->frame_hdr->film_grain.data; + return fgdata->num_y_points || fgdata->num_uv_points[0] || + fgdata->num_uv_points[1]; +} + static int output_image(Dav1dContext *const c, Dav1dPicture *const out, Dav1dPicture *const in) { - const Dav1dFilmGrainData *fgdata = &in->frame_hdr->film_grain.data; - int has_grain = fgdata->num_y_points || fgdata->num_uv_points[0] || - fgdata->num_uv_points[1]; - - // If there is nothing to be done, skip the allocation/copy - if (!c->apply_grain || !has_grain) { + if (!c->apply_grain || !has_grain(in)) { dav1d_picture_move_ref(out, in); return 0; } - // Apply film grain to a new copy of the image to avoid corrupting refs - int res = dav1d_picture_alloc_copy(c, out, in->p.w, in); - if (res < 0) { - dav1d_picture_unref_internal(in); - dav1d_picture_unref_internal(out); - return res; - } - - switch (out->p.bpc) { -#if CONFIG_8BPC - case 8: - dav1d_apply_grain_8bpc(&c->dsp[0].fg, out, in); - break; -#endif -#if CONFIG_16BPC - case 10: - case 12: - dav1d_apply_grain_16bpc(&c->dsp[(out->p.bpc >> 1) - 4].fg, out, in); - break; -#endif - default: - assert(0); - } - + int res = dav1d_apply_grain(c, out, in); dav1d_picture_unref_internal(in); - return 0; + return res; } static int output_picture_ready(Dav1dContext *const c) { @@ -453,6 +432,43 @@ int dav1d_get_picture(Dav1dContext *const c, Dav1dPicture *const out) return DAV1D_ERR(EAGAIN); } +int dav1d_apply_grain(Dav1dContext *const c, Dav1dPicture *const out, + const Dav1dPicture *const in) +{ + validate_input_or_ret(c != NULL, DAV1D_ERR(EINVAL)); + validate_input_or_ret(out != NULL, DAV1D_ERR(EINVAL)); + validate_input_or_ret(in != NULL, DAV1D_ERR(EINVAL)); + + if (!has_grain(in)) { + dav1d_picture_ref(out, in); + return 0; + } + + int res = dav1d_picture_alloc_copy(c, out, in->p.w, in); + if (res < 0) { + dav1d_picture_unref_internal(out); + return res; + } + + switch (out->p.bpc) { +#if CONFIG_8BPC + case 8: + dav1d_apply_grain_8bpc(&c->dsp[0].fg, out, in); + break; +#endif +#if CONFIG_16BPC + case 10: + case 12: + dav1d_apply_grain_16bpc(&c->dsp[(out->p.bpc >> 1) - 4].fg, out, in); + break; +#endif + default: + assert(0); + } + + return 0; +} + void dav1d_flush(Dav1dContext *const c) { dav1d_data_unref_internal(&c->in); c->drain = 0; |