diff options
Diffstat (limited to 'video/out')
-rw-r--r-- | video/out/gl_common.c | 4 | ||||
-rw-r--r-- | video/out/gl_common.h | 2 | ||||
-rw-r--r-- | video/out/gl_hwdec_vda.c | 146 | ||||
-rw-r--r-- | video/out/gl_video.c | 6 |
4 files changed, 158 insertions, 0 deletions
diff --git a/video/out/gl_common.c b/video/out/gl_common.c index e868b07559..20674de317 100644 --- a/video/out/gl_common.c +++ b/video/out/gl_common.c @@ -1038,12 +1038,16 @@ void mp_log_source(struct mp_log *log, int lev, const char *src) } extern const struct gl_hwdec_driver gl_hwdec_vaglx; +extern const struct gl_hwdec_driver gl_hwdec_vda; extern const struct gl_hwdec_driver gl_hwdec_vdpau; const struct gl_hwdec_driver *mpgl_hwdec_drivers[] = { #if HAVE_VAAPI_GLX &gl_hwdec_vaglx, #endif +#if HAVE_VDA_GL + &gl_hwdec_vda, +#endif #if HAVE_VDPAU_GL_X11 &gl_hwdec_vdpau, #endif diff --git a/video/out/gl_common.h b/video/out/gl_common.h index 3c8d1aaa98..64490b7098 100644 --- a/video/out/gl_common.h +++ b/video/out/gl_common.h @@ -202,6 +202,8 @@ struct gl_hwdec_driver { // Undo map_image(). The user of map_image() calls this when the textures // are not needed anymore. void (*unmap_image)(struct gl_hwdec *hw); + // Return a mp_image downloaded from the GPU (optional) + struct mp_image *(*download_image)(struct gl_hwdec *hw); void (*destroy)(struct gl_hwdec *hw); }; diff --git a/video/out/gl_hwdec_vda.c b/video/out/gl_hwdec_vda.c new file mode 100644 index 0000000000..65615bac6b --- /dev/null +++ b/video/out/gl_hwdec_vda.c @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2013 Stefano Pigozzi <stefano.pigozzi@gmail.com> + * + * This file is part of mpv. + * + * mpv is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with mpv. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <IOSurface/IOSurface.h> +#include <CoreVideo/CoreVideo.h> +#include <OpenGL/OpenGL.h> + +#include "video/decode/dec_video.h" +#include "cocoa_common.h" +#include "gl_common.h" + +struct priv { + CVPixelBufferRef pbuf; + GLuint gl_texture; +}; + +static bool check_hwdec(struct gl_hwdec *hw) +{ + struct vo *vo = hw->mpgl->vo; + + if (hw->gl_texture_target != GL_TEXTURE_RECTANGLE) { + MP_ERR(hw, "must use rectangle video textures with VDA\n"); + return false; + } + + if (!vo->cocoa) { + MP_ERR(hw, "need cocoa opengl backend to be active"); + return false; + } + + return true; +} + +static int create(struct gl_hwdec *hw) +{ + struct priv *p = talloc_zero(hw, struct priv); + hw->priv = p; + hw->converted_imgfmt = IMGFMT_UYVY; + hw->gl_texture_target = GL_TEXTURE_RECTANGLE; + + if (!check_hwdec(hw)) + return -1; + + GL *gl = hw->mpgl->gl; + gl->GenTextures(1, &p->gl_texture); + + return 0; +} + +static int reinit(struct gl_hwdec *hw, const struct mp_image_params *params) +{ + return 0; +} + +static int map_image(struct gl_hwdec *hw, struct mp_image *hw_image, + GLuint *out_textures) +{ + if (!check_hwdec(hw)) + return -1; + + struct priv *p = hw->priv; + struct vo *vo = hw->mpgl->vo; + GL *gl = hw->mpgl->gl; + + CVPixelBufferRelease(p->pbuf); + p->pbuf = (CVPixelBufferRef)hw_image->planes[3]; + CVPixelBufferRetain(p->pbuf); + IOSurfaceRef surface = CVPixelBufferGetIOSurface(p->pbuf); + + gl->BindTexture(hw->gl_texture_target, p->gl_texture); + + CGLError err = CGLTexImageIOSurface2D( + vo_cocoa_cgl_context(vo), hw->gl_texture_target, GL_RGB, + CVPixelBufferGetWidth(p->pbuf), CVPixelBufferGetHeight(p->pbuf), + GL_RGB_422_APPLE, GL_UNSIGNED_SHORT_8_8_APPLE, surface, 0); + + if (err != kCGLNoError) + MP_ERR(vo, "error creating IOSurface texture: %s (%x)\n", + CGLErrorString(err), gl->GetError()); + + gl->BindTexture(hw->gl_texture_target, 0); + + out_textures[0] = p->gl_texture; + return 0; +} + +static void unmap_image(struct gl_hwdec *hw) { } + +static struct mp_image *download_image(struct gl_hwdec *hw) +{ + struct priv *p = hw->priv; + CVPixelBufferLockBaseAddress(p->pbuf, 0); + void *base = CVPixelBufferGetBaseAddress(p->pbuf); + size_t width = CVPixelBufferGetWidth(p->pbuf); + size_t height = CVPixelBufferGetHeight(p->pbuf); + size_t stride = CVPixelBufferGetBytesPerRow(p->pbuf); + + struct mp_image img = {0}; + mp_image_setfmt(&img, IMGFMT_UYVY); + mp_image_set_size(&img, width, height); + img.planes[0] = base; + img.stride[0] = stride; + + struct mp_image *image = mp_image_new_copy(&img); + CVPixelBufferUnlockBaseAddress(p->pbuf, 0); + + return image; +} + +static void destroy(struct gl_hwdec *hw) +{ + struct priv *p = hw->priv; + GL *gl = hw->mpgl->gl; + + CVPixelBufferRelease(p->pbuf); + gl->DeleteTextures(1, &p->gl_texture); + p->gl_texture = 0; +} + + +const struct gl_hwdec_driver gl_hwdec_vda = { + .api_name = "vda", + .imgfmt = IMGFMT_VDA, + .create = create, + .reinit = reinit, + .map_image = map_image, + .unmap_image = unmap_image, + .download_image = download_image, + .destroy = destroy, +}; diff --git a/video/out/gl_video.c b/video/out/gl_video.c index 57dec29759..27c3339997 100644 --- a/video/out/gl_video.c +++ b/video/out/gl_video.c @@ -1699,6 +1699,12 @@ struct mp_image *gl_video_download_image(struct gl_video *p) if (!p->have_image) return NULL; + if (p->hwdec && p->hwdec->driver->download_image) { + struct mp_image *dlimage = p->hwdec->driver->download_image(p->hwdec); + mp_image_set_attributes(dlimage, &p->image_params); + return dlimage; + } + set_image_textures(p, vimg, NULL); assert(p->texture_w >= p->image_params.w); |