summaryrefslogtreecommitdiffstats
path: root/video
diff options
context:
space:
mode:
Diffstat (limited to 'video')
-rw-r--r--video/filter/refqueue.c4
-rw-r--r--video/filter/vf_gpu.c117
-rw-r--r--video/filter/vf_gpu.h35
-rw-r--r--video/filter/vf_gpu_egl.c107
-rw-r--r--video/filter/vf_gpu_vulkan.c115
-rw-r--r--video/filter/vf_vapoursynth.c33
-rw-r--r--video/image_writer.c13
-rw-r--r--video/mp_image.c2
-rw-r--r--video/out/cocoa_cb_common.swift69
-rw-r--r--video/out/d3d11/ra_d3d11.c89
-rw-r--r--video/out/drm_atomic.c54
-rw-r--r--video/out/drm_common.c2
-rw-r--r--video/out/drm_prime.c14
-rw-r--r--video/out/gpu/d3d11_helpers.c44
-rw-r--r--video/out/gpu/d3d11_helpers.h13
-rw-r--r--video/out/gpu/lcms.h2
-rw-r--r--video/out/gpu/video.c4
-rw-r--r--video/out/hwdec/dmabuf_interop_wl.c4
-rw-r--r--video/out/hwdec/hwdec_cuda.c47
-rw-r--r--video/out/hwdec/hwdec_cuda.h9
-rw-r--r--video/out/hwdec/hwdec_cuda_gl.c32
-rw-r--r--video/out/hwdec/hwdec_cuda_vk.c50
-rw-r--r--video/out/hwdec/hwdec_drmprime_overlay.c2
-rw-r--r--video/out/hwdec/hwdec_vaapi.c3
-rw-r--r--video/out/mac/common.swift57
-rw-r--r--video/out/mac/gl_layer.swift31
-rw-r--r--video/out/mac/title_bar.swift45
-rw-r--r--video/out/mac/view.swift11
-rw-r--r--video/out/mac/window.swift62
-rw-r--r--video/out/mac_common.swift15
-rw-r--r--video/out/opengl/common.c1
-rw-r--r--video/out/opengl/context_drm_egl.c3
-rw-r--r--video/out/vo_dmabuf_wayland.c16
-rw-r--r--video/out/vo_gpu_next.c5
-rw-r--r--video/out/vo_sdl.c1
-rw-r--r--video/out/vo_sixel.c4
-rw-r--r--video/out/vo_tct.c1
-rw-r--r--video/out/vo_xv.c2
-rw-r--r--video/out/vulkan/context.c58
-rw-r--r--video/out/vulkan/context.h6
-rw-r--r--video/out/w32_common.c107
-rw-r--r--video/out/wayland_common.c108
-rw-r--r--video/out/win32/menu.c17
-rw-r--r--video/out/win32/menu.h2
-rw-r--r--video/out/x11_common.c6
45 files changed, 944 insertions, 478 deletions
diff --git a/video/filter/refqueue.c b/video/filter/refqueue.c
index f5124087c6..031feb8c96 100644
--- a/video/filter/refqueue.c
+++ b/video/filter/refqueue.c
@@ -119,10 +119,10 @@ bool mp_refqueue_is_top_field(struct mp_refqueue *q)
{
if (!mp_refqueue_has_output(q))
return false;
-
+
bool tff = q->field_parity == MP_FIELD_PARITY_TFF;
bool bff = q->field_parity == MP_FIELD_PARITY_BFF;
- bool ret = (!!(q->queue[q->pos]->fields & MP_IMGFIELD_TOP_FIRST) ^ q->second_field
+ bool ret = (!!(q->queue[q->pos]->fields & MP_IMGFIELD_TOP_FIRST) ^ q->second_field
&& !tff && !bff); // Default parity
ret = ret || (tff && !q->second_field); // Check if top field is forced
ret = ret || (bff && q->second_field); // Check if bottom field is forced
diff --git a/video/filter/vf_gpu.c b/video/filter/vf_gpu.c
index e19faaef42..d2ba990a00 100644
--- a/video/filter/vf_gpu.c
+++ b/video/filter/vf_gpu.c
@@ -24,95 +24,49 @@
#include "options/options.h"
#include "video/out/aspect.h"
#include "video/out/gpu/video.h"
-#include "video/out/opengl/egl_helpers.h"
-#include "video/out/opengl/ra_gl.h"
-
-struct offscreen_ctx {
- struct mp_log *log;
- struct ra *ra;
- void *priv;
-
- void (*set_context)(struct offscreen_ctx *ctx, bool enable);
-};
-
-struct gl_offscreen_ctx {
- GL gl;
- EGLDisplay egl_display;
- EGLContext egl_context;
+#include "video/filter/vf_gpu.h"
+
+extern const struct offscreen_context offscreen_vk;
+extern const struct offscreen_context offscreen_egl;
+
+static const struct offscreen_context *contexts[] = {
+#if HAVE_EGL
+ &offscreen_egl,
+#endif
+#if HAVE_VULKAN
+ &offscreen_vk,
+#endif
};
-static void gl_ctx_destroy(void *p)
+static inline OPT_STRING_VALIDATE_FUNC(offscreen_ctx_validate_api)
{
- struct offscreen_ctx *ctx = p;
- struct gl_offscreen_ctx *gl = ctx->priv;
-
- ra_free(&ctx->ra);
-
- if (gl->egl_context)
- eglDestroyContext(gl->egl_display, gl->egl_context);
+ struct bstr param = bstr0(*value);
+ for (int i = 0; i < MP_ARRAY_SIZE(contexts); i++) {
+ if (bstr_equals0(param, contexts[i]->api))
+ return 1;
+ }
+ return M_OPT_INVALID;
}
-static void gl_ctx_set_context(struct offscreen_ctx *ctx, bool enable)
+static int offscreen_ctx_api_help(struct mp_log *log, const struct m_option *opt,
+ struct bstr name)
{
- struct gl_offscreen_ctx *gl = ctx->priv;
- EGLContext c = enable ? gl->egl_context : EGL_NO_CONTEXT;
-
- if (!eglMakeCurrent(gl->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, c))
- MP_ERR(ctx, "Could not make EGL context current.\n");
+ mp_info(log, "GPU APIs (offscreen contexts):\n");
+ for (int i = 0; i < MP_ARRAY_SIZE(contexts); i++)
+ mp_info(log, " %s\n", contexts[i]->api);
+ return M_OPT_EXIT;
}
-static struct offscreen_ctx *gl_offscreen_ctx_create(struct mpv_global *global,
- struct mp_log *log)
+static struct offscreen_ctx *offscreen_ctx_create(struct mpv_global *global,
+ struct mp_log *log,
+ const char *api)
{
- struct offscreen_ctx *ctx = talloc_zero(NULL, struct offscreen_ctx);
- struct gl_offscreen_ctx *gl = talloc_zero(ctx, struct gl_offscreen_ctx);
- talloc_set_destructor(ctx, gl_ctx_destroy);
- *ctx = (struct offscreen_ctx){
- .log = log,
- .priv = gl,
- .set_context = gl_ctx_set_context,
- };
-
- // This appears to work with Mesa. EGL 1.5 doesn't specify what a "default
- // display" is at all.
- gl->egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- if (!eglInitialize(gl->egl_display, NULL, NULL)) {
- MP_ERR(ctx, "Could not initialize EGL.\n");
- goto error;
+ for (int i = 0; i < MP_ARRAY_SIZE(contexts); i++) {
+ if (api && strcmp(contexts[i]->api, api) != 0)
+ continue;
+ mp_info(log, "Creating offscreen GPU context '%s'\n", contexts[i]->api);
+ return contexts[i]->offscreen_ctx_create(global, log);
}
-
- // Unfortunately, mpegl_create_context() is entangled with ra_ctx.
- // Fortunately, it does not need much, and we can provide a stub.
- struct ra_ctx ractx = {
- .log = ctx->log,
- .global = global,
- };
- EGLConfig config;
- if (!mpegl_create_context(&ractx, gl->egl_display, &gl->egl_context, &config))
- {
- MP_ERR(ctx, "Could not create EGL context.\n");
- goto error;
- }
-
- if (!eglMakeCurrent(gl->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
- gl->egl_context))
- {
- MP_ERR(ctx, "Could not make EGL context current.\n");
- goto error;
- }
-
- mpegl_load_functions(&gl->gl, ctx->log);
- ctx->ra = ra_create_gl(&gl->gl, ctx->log);
-
- if (!ctx->ra)
- goto error;
-
- gl_ctx_set_context(ctx, false);
-
- return ctx;
-
-error:
- talloc_free(ctx);
return NULL;
}
@@ -124,6 +78,7 @@ static void offscreen_ctx_set_current(struct offscreen_ctx *ctx, bool enable)
struct gpu_opts {
int w, h;
+ char *api;
};
struct priv {
@@ -327,7 +282,7 @@ static struct mp_filter *gpu_create(struct mp_filter *parent, void *options)
priv->vo_opts_cache = m_config_cache_alloc(f, f->global, &vo_sub_opts);
priv->vo_opts = priv->vo_opts_cache->opts;
- priv->ctx = gl_offscreen_ctx_create(f->global, f->log);
+ priv->ctx = offscreen_ctx_create(f->global, f->log, priv->opts->api);
if (!priv->ctx) {
MP_FATAL(f, "Could not create offscreen ra context.\n");
goto error;
@@ -368,6 +323,8 @@ const struct mp_user_filter_entry vf_gpu = {
.options = (const struct m_option[]){
{"w", OPT_INT(w)},
{"h", OPT_INT(h)},
+ {"api", OPT_STRING_VALIDATE(api, offscreen_ctx_validate_api),
+ .help = offscreen_ctx_api_help},
{0}
},
},
diff --git a/video/filter/vf_gpu.h b/video/filter/vf_gpu.h
new file mode 100644
index 0000000000..2cc9a16eea
--- /dev/null
+++ b/video/filter/vf_gpu.h
@@ -0,0 +1,35 @@
+/*
+ * This file is part of mpv.
+ *
+ * mpv is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * mpv is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with mpv. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include "common/common.h"
+#include "common/global.h"
+
+struct offscreen_ctx {
+ struct mp_log *log;
+ struct ra *ra;
+ void *priv;
+
+ void (*set_context)(struct offscreen_ctx *ctx, bool enable);
+};
+
+struct offscreen_context {
+ const char *api;
+ struct offscreen_ctx *(*offscreen_ctx_create)(struct mpv_global *,
+ struct mp_log *);
+};
diff --git a/video/filter/vf_gpu_egl.c b/video/filter/vf_gpu_egl.c
new file mode 100644
index 0000000000..cd90a6e06a
--- /dev/null
+++ b/video/filter/vf_gpu_egl.c
@@ -0,0 +1,107 @@
+/*
+ * This file is part of mpv.
+ *
+ * mpv is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * mpv is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with mpv. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "common/common.h"
+#include "video/filter/vf_gpu.h"
+#include "video/out/opengl/egl_helpers.h"
+#include "video/out/opengl/ra_gl.h"
+
+struct gl_offscreen_ctx {
+ GL gl;
+ EGLDisplay egl_display;
+ EGLContext egl_context;
+};
+
+static void gl_ctx_destroy(void *p)
+{
+ struct offscreen_ctx *ctx = p;
+ struct gl_offscreen_ctx *gl = ctx->priv;
+
+ ra_free(&ctx->ra);
+
+ if (gl->egl_context)
+ eglDestroyContext(gl->egl_display, gl->egl_context);
+}
+
+static void gl_ctx_set_context(struct offscreen_ctx *ctx, bool enable)
+{
+ struct gl_offscreen_ctx *gl = ctx->priv;
+ EGLContext c = enable ? gl->egl_context : EGL_NO_CONTEXT;
+
+ if (!eglMakeCurrent(gl->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, c))
+ MP_ERR(ctx, "Could not make EGL context current.\n");
+}
+
+static struct offscreen_ctx *gl_offscreen_ctx_create(struct mpv_global *global,
+ struct mp_log *log)
+{
+ struct offscreen_ctx *ctx = talloc(NULL, struct offscreen_ctx);
+ struct gl_offscreen_ctx *gl = talloc_zero(ctx, struct gl_offscreen_ctx);
+ talloc_set_destructor(ctx, gl_ctx_destroy);
+ *ctx = (struct offscreen_ctx){
+ .log = log,
+ .priv = gl,
+ .set_context = gl_ctx_set_context,
+ };
+
+ // This appears to work with Mesa. EGL 1.5 doesn't specify what a "default
+ // display" is at all.
+ gl->egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ if (!eglInitialize(gl->egl_display, NULL, NULL)) {
+ MP_ERR(ctx, "Could not initialize EGL.\n");
+ goto error;
+ }
+
+ // Unfortunately, mpegl_create_context() is entangled with ra_ctx.
+ // Fortunately, it does not need much, and we can provide a stub.
+ struct ra_ctx ractx = {
+ .log = ctx->log,
+ .global = global,
+ };
+ EGLConfig config;
+ if (!mpegl_create_context(&ractx, gl->egl_display, &gl->egl_context, &config))
+ {
+ MP_ERR(ctx, "Could not create EGL context.\n");
+ goto error;
+ }
+
+ if (!eglMakeCurrent(gl->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
+ gl->egl_context))
+ {
+ MP_ERR(ctx, "Could not make EGL context current.\n");
+ goto error;
+ }
+
+ mpegl_load_functions(&gl->gl, ctx->log);
+ ctx->ra = ra_create_gl(&gl->gl, ctx->log);
+
+ if (!ctx->ra)
+ goto error;
+
+ gl_ctx_set_context(ctx, false);
+
+ return ctx;
+
+error:
+ talloc_free(ctx);
+ return NULL;
+}
+
+const struct offscreen_context offscreen_egl = {
+ .api = "egl",
+ .offscreen_ctx_create = gl_offscreen_ctx_create
+};
diff --git a/video/filter/vf_gpu_vulkan.c b/video/filter/vf_gpu_vulkan.c
new file mode 100644
index 0000000000..d477fd153a
--- /dev/null
+++ b/video/filter/vf_gpu_vulkan.c
@@ -0,0 +1,115 @@
+/*
+ * This file is part of mpv.
+ *
+ * mpv is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * mpv is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with mpv. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "options/m_config.h"
+#include "video/filter/vf_gpu.h"
+#include "video/out/placebo/ra_pl.h"
+#include "video/out/placebo/utils.h"
+#include "video/out/vulkan/context.h"
+#include "video/out/vulkan/utils.h"
+
+struct vk_offscreen_ctx {
+ struct ra_ctx *ractx;
+ struct mpvk_ctx *vk;
+};
+
+extern const struct m_sub_options vulkan_conf;
+
+static void vk_ctx_destroy(void *p)
+{
+ struct offscreen_ctx *ctx = p;
+ struct vk_offscreen_ctx *vkctx = ctx->priv;
+ struct ra_ctx *ractx = vkctx->ractx;
+ struct mpvk_ctx *vk = vkctx->vk;
+
+ if (ractx->ra) {
+ pl_gpu_finish(vk->gpu);
+ ractx->ra->fns->destroy(ctx->ra);
+ ractx->ra = NULL;
+ ctx->ra = NULL;
+ }
+
+ vk->gpu = NULL;
+ pl_vulkan_destroy(&vk->vulkan);
+ mpvk_uninit(vk);
+ talloc_free(vk);
+ talloc_free(ractx);
+}
+
+static struct offscreen_ctx *vk_offscreen_ctx_create(struct mpv_global *global,
+ struct mp_log *log)
+{
+ struct offscreen_ctx *ctx = talloc(NULL, struct offscreen_ctx);
+ talloc_set_destructor(ctx, vk_ctx_destroy);
+ *ctx = (struct offscreen_ctx){
+ .log = log,
+ };
+
+ struct ra_ctx *ractx = talloc_zero(ctx, struct ra_ctx);
+ struct mpvk_ctx *vk = talloc_zero(ctx, struct mpvk_ctx);
+ ractx->log = ctx->log;
+ ractx->global = global;
+
+ vk->pllog = mppl_log_create(ctx, log);
+ if (!vk->pllog)
+ goto error;
+
+ struct pl_vk_inst_params pl_vk_params = {0};
+ struct ra_ctx_opts *ctx_opts = mp_get_config_group(NULL, global, &ra_ctx_conf);
+ pl_vk_params.debug = ctx_opts->debug;
+ talloc_free(ctx_opts);
+ mppl_log_set_probing(vk->pllog, true);
+ vk->vkinst = pl_vk_inst_create(vk->pllog, &pl_vk_params);
+ mppl_log_set_probing(vk->pllog, false);
+ if (!vk->vkinst)
+ goto error;
+
+ struct vulkan_opts *vk_opts = mp_get_config_group(NULL, global, &vulkan_conf);
+ vk->vulkan = mppl_create_vulkan(vk_opts, vk->vkinst, vk->pllog, VK_NULL_HANDLE);
+ talloc_free(vk_opts);
+ if (!vk->vulkan)
+ goto error;
+
+ vk->gpu = vk->vulkan->gpu;
+ ractx->ra = ra_create_pl(vk->gpu, ractx->log);
+ if (!ractx->ra)
+ goto error;
+
+ struct vk_offscreen_ctx *vkctx = talloc(ctx, struct vk_offscreen_ctx);
+ *vkctx = (struct vk_offscreen_ctx){
+ .ractx = ractx,
+ .vk = vk
+ };
+
+ ctx->ra = ractx->ra;
+ ctx->priv = vkctx;
+
+ return ctx;
+
+error:
+ pl_vulkan_destroy(&vk->vulkan);
+ mpvk_uninit(vk);
+ talloc_free(vk);
+ talloc_free(ractx);
+ talloc_free(ctx);
+ return NULL;
+}
+
+const struct offscreen_context offscreen_vk = {
+ .api = "vulkan",
+ .offscreen_ctx_create = vk_offscreen_ctx_create
+};
diff --git a/video/filter/vf_vapoursynth.c b/video/filter/vf_vapoursynth.c
index 0b798c8daf..597ef5cbf2 100644
--- a/video/filter/vf_vapoursynth.c
+++ b/video/filter/vf_vapoursynth.c
@@ -193,8 +193,9 @@ static void copy_mp_to_vs_frame_props_map(struct priv *p, VSMap *map,
p->vsapi->propSetInt(map, "_ColorSpace",
pl_system_to_av(params->repr.sys), 0);
if (params->chroma_location) {
+ // 0=left, 1=center, 2=topleft, 3=top, 4=bottomleft, 5=bottom.
p->vsapi->propSetInt(map, "_ChromaLocation",
- params->chroma_location == PL_CHROMA_CENTER, 0);
+ params->chroma_location - 1, 0);
}
char pict_type = 0;
switch (img->pict_type) {
@@ -208,6 +209,10 @@ static void copy_mp_to_vs_frame_props_map(struct priv *p, VSMap *map,
if (img->fields & MP_IMGFIELD_INTERLACED)
field = img->fields & MP_IMGFIELD_TOP_FIRST ? 2 : 1;
p->vsapi->propSetInt(map, "_FieldBased", field, 0);
+
+ // Don't increase the reference count. It is not intended to be read externally,
+ // and we know it will be alive when we retrieve it.
+ p->vsapi->propSetData(map, "_MP_IMAGE", (const char *)img, sizeof(*img), 0);
}
static int set_vs_frame_props(struct priv *p, VSFrameRef *frame,
@@ -230,11 +235,13 @@ static VSFrameRef *alloc_vs_frame(struct priv *p, struct mp_image_params *fmt)
}
static struct mp_image map_vs_frame(struct priv *p, const VSFrameRef *ref,
- bool w)
+ bool w, struct mp_image *ref_image)
{
const VSFormat *fmt = p->vsapi->getFrameFormat(ref);
struct mp_image img = {0};
+ if (ref_image)
+ img = *ref_image;
mp_image_setfmt(&img, mp_from_vs(fmt->id));
mp_image_set_size(&img, p->vsapi->getFrameWidth(ref, 0),
p->vsapi->getFrameHeight(ref, 0));
@@ -269,13 +276,19 @@ static void VS_CC vs_frame_done(void *userData, const VSFrameRef *f, int n,
struct mp_image *res = NULL;
if (f) {
- struct mp_image img = map_vs_frame(p, f, false);
- struct mp_image dummy = {.params = p->fmt_in};
- if (p->fmt_in.w != img.w || p->fmt_in.h != img.h)
- dummy.params.crop = (struct mp_rect){0, 0, img.w, img.h};
- mp_image_copy_attributes(&img, &dummy);
- img.pkt_duration = -1;
const VSMap *map = p->vsapi->getFramePropsRO(f);
+ if (!map)
+ MP_ERR(p, "Failed to get frame properties!");
+ struct mp_image *mpi = NULL;
+ if (map) {
+ mpi = (void *)p->vsapi->propGetData(map, "_MP_IMAGE", 0, NULL);
+ if (!mpi)
+ MP_ERR(p, "Failed to get mp_image attributes!");
+ }
+ struct mp_image img = map_vs_frame(p, f, false, mpi);
+ img.pkt_duration = -1;
+ if (mpi && (mpi->params.w != img.w || mpi->params.h != img.h))
+ img.params.crop = (struct mp_rect){0, 0, img.w, img.h};
if (map) {
int err1, err2;
int num = p->vsapi->propGetInt(map, "_DurationNum", 0, &err1);
@@ -490,7 +503,7 @@ static const VSFrameRef *VS_CC infiltGetFrame(int frameno, int activationReason,
p->vsapi->setFilterError("Could not allocate VS frame", frameCtx);
break;
}
- struct mp_image vsframe = map_vs_frame(p, ret, true);
+ struct mp_image vsframe = map_vs_frame(p, ret, true, NULL);
mp_image_clear(&vsframe, 0, 0, p->fmt_in.w, p->fmt_in.h);
struct mp_image dummy = {0};
mp_image_set_params(&dummy, &p->fmt_in);
@@ -538,7 +551,7 @@ static const VSFrameRef *VS_CC infiltGetFrame(int frameno, int activationReason,
}
mp_mutex_unlock(&p->lock);
- struct mp_image vsframe = map_vs_frame(p, ret, true);
+ struct mp_image vsframe = map_vs_frame(p, ret, true, NULL);
mp_image_copy(&vsframe, img);
int res = 1e6;
int dur = img->pkt_duration * res + 0.5;
diff --git a/video/image_writer.c b/video/image_writer.c
index cc795735ef..3c2d57a80f 100644
--- a/video/image_writer.c
+++ b/video/image_writer.c
@@ -19,7 +19,6 @@
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
-#include <unistd.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
@@ -221,7 +220,7 @@ static bool write_lavc(struct image_writer_ctx *ctx, mp_image_t *image, FILE *fp
}
if (avcodec_open2(avctx, codec, NULL) < 0) {
- print_open_fail:
+ print_open_fail:
MP_ERR(ctx, "Could not open libavcodec encoder for saving images\n");
goto error_exit;
}
@@ -261,11 +260,11 @@ error_exit:
static void write_jpeg_error_exit(j_common_ptr cinfo)
{
- // NOTE: do not write error message, too much effort to connect the libjpeg
- // log callbacks with mplayer's log function mp_msp()
+ // NOTE: do not write error message, too much effort to connect the libjpeg
+ // log callbacks with mplayer's log function mp_msp()
- // Return control to the setjmp point
- longjmp(*(jmp_buf*)cinfo->client_data, 1);
+ // Return control to the setjmp point
+ longjmp(*(jmp_buf*)cinfo->client_data, 1);
}
static bool write_jpeg(struct image_writer_ctx *ctx, mp_image_t *image, FILE *fp)
@@ -309,7 +308,7 @@ static bool write_jpeg(struct image_writer_ctx *ctx, mp_image_t *image, FILE *fp
JSAMPROW row_pointer[1];
row_pointer[0] = image->planes[0] +
(ptrdiff_t)cinfo.next_scanline * image->stride[0];
- jpeg_write_scanlines(&cinfo, row_pointer,1);
+ jpeg_write_scanlines(&cinfo, row_pointer, 1);
}
jpeg_finish_compress(&cinfo);
diff --git a/video/mp_image.c b/video/mp_image.c
index 609fb17bf0..35b302d328 100644
--- a/video/mp_image.c
+++ b/video/mp_image.c
@@ -1116,10 +1116,8 @@ struct mp_image *mp_image_from_av_frame(struct AVFrame *src)
sd = av_frame_get_side_data(src, AV_FRAME_DATA_DOVI_RPU_BUFFER);
if (sd) {
-#ifdef PL_HAVE_LIBDOVI
pl_hdr_metadata_from_dovi_rpu(&dst->params.color.hdr, sd->buf->data,
sd->buf->size);
-#endif
}
#endif
diff --git a/video/out/cocoa_cb_common.swift b/video/out/cocoa_cb_common.swift
index 9f32ed651f..b2910dba85 100644
--- a/video/out/cocoa_cb_common.swift
+++ b/video/out/cocoa_cb_common.swift
@@ -87,8 +87,7 @@ class CocoaCB: Common, EventSubscriber {
}
func updateWindowSize(_ vo: UnsafeMutablePointer<vo>) {
- guard let targetScreen = getTargetScreen(forFullscreen: false) ?? NSScreen.main else
- {
+ guard let targetScreen = getTargetScreen(forFullscreen: false) ?? NSScreen.main else {
log.warning("Couldn't update Window size, no Screen available")
return
}
@@ -102,11 +101,10 @@ class CocoaCB: Common, EventSubscriber {
}
override func displayLinkCallback(_ displayLink: CVDisplayLink,
- _ inNow: UnsafePointer<CVTimeStamp>,
- _ inOutputTime: UnsafePointer<CVTimeStamp>,
- _ flagsIn: CVOptionFlags,
- _ flagsOut: UnsafeMutablePointer<CVOptionFlags>) -> CVReturn
- {
+ _ inNow: UnsafePointer<CVTimeStamp>,
+ _ inOutputTime: UnsafePointer<CVTimeStamp>,
+ _ flagsIn: CVOptionFlags,
+ _ flagsOut: UnsafeMutablePointer<CVOptionFlags>) -> CVReturn {
libmpv.reportRenderFlip()
return kCVReturnSuccess
}
@@ -122,7 +120,55 @@ class CocoaCB: Common, EventSubscriber {
}
libmpv.setRenderICCProfile(colorSpace)
- layer?.colorspace = colorSpace.cgColorSpace
+ layer?.colorspace = getColorSpace()
+ }
+
+ func getColorSpace() -> CGColorSpace? {
+ guard let colorSpace = window?.screen?.colorSpace?.cgColorSpace else {
+ log.warning("Couldn't retrieve ICC Profile, no color space available")
+ return nil
+ }
+
+ let outputCsp = Int(option.mac.cocoa_cb_output_csp)
+
+ switch outputCsp {
+ case MAC_CSP_AUTO: return colorSpace
+ case MAC_CSP_DISPLAY_P3: return CGColorSpace(name: CGColorSpace.displayP3)
+ case MAC_CSP_DISPLAY_P3_HLG: return CGColorSpace(name: CGColorSpace.displayP3_HLG)
+ case MAC_CSP_DISPLAY_P3_PQ: return CGColorSpace(name: CGColorSpace.displayP3_PQ)
+ case MAC_CSP_DCI_P3: return CGColorSpace(name: CGColorSpace.dcip3)
+ case MAC_CSP_BT_2020: return CGColorSpace(name: CGColorSpace.itur_2020)
+ case MAC_CSP_BT_709: return CGColorSpace(name: CGColorSpace.itur_709)
+ case MAC_CSP_SRGB: return CGColorSpace(name: CGColorSpace.sRGB)
+ case MAC_CSP_SRGB_LINEAR: return CGColorSpace(name: CGColorSpace.linearSRGB)
+ case MAC_CSP_RGB_LINEAR: return CGColorSpace(name: CGColorSpace.genericRGBLinear)
+ case MAC_CSP_ADOBE: return CGColorSpace(name: CGColorSpace.adobeRGB1998)
+ default: break
+ }
+
+#if HAVE_MACOS_11_FEATURES
+ if #available(macOS 11.0, *) {
+ switch outputCsp {
+ case MAC_CSP_BT_2100_HLG: return CGColorSpace(name: CGColorSpace.itur_2100_HLG)
+ case MAC_CSP_BT_2100_PQ: return CGColorSpace(name: CGColorSpace.itur_2100_PQ)
+ default: break
+ }
+ }
+#endif
+
+#if HAVE_MACOS_12_FEATURES
+ if #available(macOS 12.0, *) {
+ switch outputCsp {
+ case MAC_CSP_DISPLAY_P3_LINEAR: return CGColorSpace(name: CGColorSpace.linearDisplayP3)
+ case MAC_CSP_BT_2020_LINEAR: return CGColorSpace(name: CGColorSpace.linearITUR_2020)
+ default: break
+ }
+ }
+#endif
+
+