diff options
-rw-r--r-- | DOCS/man/vo.rst | 11 | ||||
-rw-r--r-- | video/out/gl_lcms.c | 55 | ||||
-rw-r--r-- | video/out/gl_lcms.h | 2 |
3 files changed, 40 insertions, 28 deletions
diff --git a/DOCS/man/vo.rst b/DOCS/man/vo.rst index b398d4f57d..ead2f7b47e 100644 --- a/DOCS/man/vo.rst +++ b/DOCS/man/vo.rst @@ -669,11 +669,14 @@ Available video output drivers are: NOTE: Only implemented on OS X and X11 - ``icc-cache=<file>`` - Store and load the 3D LUT created from the ICC profile in this file. + ``icc-cache-dir=<dirname>`` + Store and load the 3D LUTs created from the ICC profile in this directory. This can be used to speed up loading, since LittleCMS 2 can take a while - to create the 3D LUT. Note that this file contains an uncompressed LUT. - Its size depends on the ``3dlut-size``, and can be very big. + to create a 3D LUT. Note that these files contain uncompressed LUTs. + Their size depends on the ``3dlut-size``, and can be very big. + + NOTE: This is not cleaned automatically, so old, unused cache files + may stick around indefinitely. ``icc-intent=<value>`` Specifies the ICC intent used for the color transformation (when using diff --git a/video/out/gl_lcms.c b/video/out/gl_lcms.c index ab273ffc0b..e49ce77a23 100644 --- a/video/out/gl_lcms.c +++ b/video/out/gl_lcms.c @@ -39,6 +39,8 @@ #if HAVE_LCMS2 #include <lcms2.h> +#include <libavutil/sha.h> +#include <libavutil/mem.h> struct gl_lcms { void *icc_data; @@ -77,9 +79,11 @@ const struct m_sub_options mp_icc_conf = { .opts = (const m_option_t[]) { OPT_STRING("icc-profile", profile, 0), OPT_FLAG("icc-profile-auto", profile_auto, 0), - OPT_STRING("icc-cache", cache, 0), + OPT_STRING("icc-cache-dir", cache_dir, 0), OPT_INT("icc-intent", intent, 0), OPT_STRING_VALIDATE("3dlut-size", size_str, 0, validate_3dlut_size_opt), + + OPT_REMOVED("icc-cache", "see icc-cache-dir"), {0} }, .size = sizeof(struct mp_icc_opts), @@ -185,8 +189,6 @@ bool gl_lcms_has_changed(struct gl_lcms *p) return change; } -#define LUT3D_CACHE_HEADER "mpv 3dlut cache 1.0\n" - bool gl_lcms_get_lut3d(struct gl_lcms *p, struct lut3d **result_lut3d) { int s_r, s_g, s_b; @@ -203,27 +205,36 @@ bool gl_lcms_get_lut3d(struct gl_lcms *p, struct lut3d **result_lut3d) struct lut3d *lut = NULL; cmsContext cms = NULL; - char *cache_info = + char *cache_file = NULL; + if (p->opts.cache_dir) { // Gamma is included in the header to help uniquely identify it, // because we may change the parameter in the future or make it // customizable, same for the primaries. - talloc_asprintf(tmp, "intent=%d, size=%dx%dx%d, gamma=2.4, prim=bt2020\n", - p->opts.intent, s_r, s_g, s_b); - - bstr iccdata = (bstr) { - .start = p->icc_data, - .len = p->icc_size, - }; + char *cache_info = talloc_asprintf(tmp, + "ver=1.1, intent=%d, size=%dx%dx%d, gamma=2.4, prim=bt2020\n", + p->opts.intent, s_r, s_g, s_b); + + uint8_t hash[32]; + struct AVSHA *sha = av_sha_alloc(); + if (!sha) + abort(); + av_sha_init(sha, 256); + av_sha_update(sha, cache_info, strlen(cache_info)); + av_sha_update(sha, p->icc_data, p->icc_size); + av_sha_final(sha, hash); + av_free(sha); + + cache_file = talloc_strdup(tmp, p->opts.cache_dir); + cache_file = talloc_asprintf_append(cache_file, "/"); + for (int i = 0; i < sizeof(hash); i++) + cache_file = talloc_asprintf_append(cache_file, "%02X", hash[i]); + } // check cache - if (p->opts.cache) { - MP_INFO(p, "Opening 3D LUT cache in file '%s'.\n", p->opts.cache); - struct bstr cachedata = load_file(tmp, p->opts.cache, p->global); - if (bstr_eatstart(&cachedata, bstr0(LUT3D_CACHE_HEADER)) - && bstr_eatstart(&cachedata, bstr0(cache_info)) - && bstr_eatstart(&cachedata, iccdata) - && cachedata.len == talloc_get_size(output)) - { + if (cache_file) { + MP_INFO(p, "Opening 3D LUT cache in file '%s'.\n", cache_file); + struct bstr cachedata = load_file(tmp, cache_file, p->global); + if (cachedata.len == talloc_get_size(output)) { memcpy(output, cachedata.start, cachedata.len); goto done; } else { @@ -284,12 +295,10 @@ bool gl_lcms_get_lut3d(struct gl_lcms *p, struct lut3d **result_lut3d) cmsDeleteTransform(trafo); - if (p->opts.cache) { - char *fname = mp_get_user_path(NULL, p->global, p->opts.cache); + if (cache_file) { + char *fname = mp_get_user_path(NULL, p->global, cache_file); FILE *out = fopen(fname, "wb"); if (out) { - fprintf(out, "%s%s", LUT3D_CACHE_HEADER, cache_info); - fwrite(p->icc_data, p->icc_size, 1, out); fwrite(output, talloc_get_size(output), 1, out); fclose(out); } diff --git a/video/out/gl_lcms.h b/video/out/gl_lcms.h index 883b485f66..5ad08b7d64 100644 --- a/video/out/gl_lcms.h +++ b/video/out/gl_lcms.h @@ -10,7 +10,7 @@ extern const struct m_sub_options mp_icc_conf; struct mp_icc_opts { char *profile; int profile_auto; - char *cache; + char *cache_dir; char *size_str; int intent; }; |