1
mirror of https://github.com/mpv-player/mpv synced 2024-09-28 17:52:52 +02:00

vo_opengl: gl_lcms: replace icc-cache by icc-cache-dir

This now stores caches for multiple ICC profiles, potentially all the
user has ever used. The big use case for this is for users with multiple
monitors. The old logic would mandate recomputing the LUT and discarding
the cache whenever dragging mpv from one screen to another.

This also avoids having to save and check the ICC profile itself, since
the file name already uniquely determines it.
This commit is contained in:
Niklas Haas 2015-04-29 18:09:22 +02:00 committed by wm4
parent 47d46ec487
commit 1153f13bee
3 changed files with 39 additions and 27 deletions

View File

@ -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

View File

@ -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);
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);
bstr iccdata = (bstr) {
.start = p->icc_data,
.len = p->icc_size,
};
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);
}

View File

@ -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;
};