diff options
author | wm4 <wm4@nowhere> | 2013-11-04 00:00:18 +0100 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2013-11-04 00:11:07 +0100 |
commit | 571e697a7c557d10bcc9130915c431829981d877 (patch) | |
tree | 027490a8aca629a9c3d321556b5bc6da5159d844 /video/out/vo_opengl.c | |
parent | 6f17410f88fd3765b6598b4e706b1d03ee85efe8 (diff) | |
download | mpv-571e697a7c557d10bcc9130915c431829981d877.tar.bz2 mpv-571e697a7c557d10bcc9130915c431829981d877.tar.xz |
vo_opengl: add infrastructure for hardware decoding OpenGL interop
Most hardware decoding APIs provide some OpenGL interop. This allows
using vo_opengl, without having to read the video data back from GPU.
This requires adding a backend for each hardware decoding API. (Each
backend is an entry in gl_hwdec_vaglx[].) The backends expose video data
as a set of OpenGL textures.
Add infrastructure to support this. The next commit will add support for
VA-API.
Diffstat (limited to 'video/out/vo_opengl.c')
-rw-r--r-- | video/out/vo_opengl.c | 73 |
1 files changed, 72 insertions, 1 deletions
diff --git a/video/out/vo_opengl.c b/video/out/vo_opengl.c index cf1b3b3400..8572f587a4 100644 --- a/video/out/vo_opengl.c +++ b/video/out/vo_opengl.c @@ -48,6 +48,7 @@ #include "gl_osd.h" #include "filter_kernels.h" #include "video/memcpy_pic.h" +#include "video/decode/dec_video.h" #include "gl_video.h" #include "gl_lcms.h" @@ -58,6 +59,8 @@ struct gl_priv { struct gl_video *renderer; + struct gl_hwdec *hwdec; + // Options struct gl_video_opts *renderer_opts; struct mp_icc_opts *icc_opts; @@ -134,8 +137,9 @@ static void draw_image(struct vo *vo, mp_image_t *mpi) static int query_format(struct vo *vo, uint32_t format) { + struct gl_priv *p = vo->priv; int caps = VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_FLIP; - if (!gl_video_check_format(format)) + if (!gl_video_check_format(p->renderer, format)) return 0; return caps; } @@ -191,6 +195,68 @@ static int reconfig(struct vo *vo, struct mp_image_params *params, int flags) return 0; } + +static void load_hwdec_driver(struct gl_priv *p, + const struct gl_hwdec_driver *drv) +{ + assert(!p->hwdec); + struct gl_hwdec *hwdec = talloc(NULL, struct gl_hwdec); + *hwdec = (struct gl_hwdec) { + .driver = drv, + .log = mp_log_new(hwdec, p->vo->log, drv->api_name), + .mpgl = p->glctx, + .info = talloc_zero(hwdec, struct mp_hwdec_info), + }; + mpgl_lock(p->glctx); + if (hwdec->driver->create(hwdec) < 0) { + mpgl_unlock(p->glctx); + talloc_free(hwdec); + MP_ERR(p->vo, "Couldn't load hwdec driver '%s'\n", drv->api_name); + return; + } + p->hwdec = hwdec; + gl_video_set_hwdec(p->renderer, p->hwdec); + mpgl_unlock(p->glctx); +} + +static void request_hwdec_api(struct mp_hwdec_info *info, const char *api_name) +{ + struct gl_priv *p = info->load_api_ctx; + // Load at most one hwdec API + if (p->hwdec) + return; + for (int n = 0; mpgl_hwdec_drivers[n]; n++) { + const struct gl_hwdec_driver *drv = mpgl_hwdec_drivers[n]; + if (api_name && strcmp(drv->api_name, api_name) == 0) { + load_hwdec_driver(p, drv); + if (p->hwdec) { + *info = *p->hwdec->info; + return; + } + } + } +} + +static void get_hwdec_info(struct gl_priv *p, struct mp_hwdec_info *info) +{ + info->load_api = request_hwdec_api; + info->load_api_ctx = p; + if (p->hwdec) + *info = *p->hwdec->info; +} + +static void unload_hwdec_driver(struct gl_priv *p) +{ + if (p->hwdec) { + mpgl_lock(p->glctx); + gl_video_set_hwdec(p->renderer, NULL); + p->hwdec->driver->destroy(p->hwdec); + talloc_free(p->hwdec); + p->hwdec = NULL; + mpgl_unlock(p->glctx); + } +} + static bool reparse_cmdline(struct gl_priv *p, char *args) { struct m_config *cfg = NULL; @@ -263,6 +329,10 @@ static int control(struct vo *vo, uint32_t request, void *data) mpgl_unlock(p->glctx); return true; } + case VOCTRL_GET_HWDEC_INFO: { + get_hwdec_info(p, data); + return true; + } case VOCTRL_REDRAW_FRAME: mpgl_lock(p->glctx); gl_video_render_frame(p->renderer); @@ -291,6 +361,7 @@ static void uninit(struct vo *vo) struct gl_priv *p = vo->priv; if (p->glctx) { + unload_hwdec_driver(p); if (p->renderer) gl_video_uninit(p->renderer); mpgl_uninit(p->glctx); |