diff options
-rwxr-xr-x | old-configure | 13 | ||||
-rw-r--r-- | old-makefile | 1 | ||||
-rw-r--r-- | video/decode/vda.c | 3 | ||||
-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 | ||||
-rw-r--r-- | wscript | 5 | ||||
-rw-r--r-- | wscript_build.py | 1 |
9 files changed, 181 insertions, 0 deletions
diff --git a/old-configure b/old-configure index 526991e72d..45e7add61b 100755 --- a/old-configure +++ b/old-configure @@ -2851,9 +2851,20 @@ else fi echores "$_vda_refcounting" +echocheck "VDA with OpenGL" +if test "$_gl_cocoa" = yes && test "$_vda" = yes ; then + def_vda_gl='#define HAVE_VDA_GL 1' + _vda_gl=yes +else + def_vda_gl='#define HAVE_VDA_GL 0' + _vda_gl=no +fi +echores "$_vda_gl" + else def_vda='#define HAVE_VDA_HWACCEL 0' def_vda_refcounting='#define HAVE_VDA_LIBAVCODEC_REFCOUNTING 0' + def_vda_gl='#define HAVE_VDA_GL 0' fi @@ -3290,6 +3301,7 @@ VDPAU_DEC_OLD = $_vdpau_dec_old VDPAU_GL_X11 = $_vdpau_gl_x11 VDA = $_vda VDA_REFCOUNTING = $_vda_refcounting +VDA_GL = $_vda_gl VAAPI = $_vaapi VAAPI_VPP = $_vaapi_vpp VAAPI_GLX = $_vaapi_glx @@ -3471,6 +3483,7 @@ $def_vdpau_dec $def_vdpau_dec_old $def_vdpau_gl_x11 $def_vda +$def_vda_gl $def_vda_refcounting $def_vaapi $def_vaapi_vpp diff --git a/old-makefile b/old-makefile index 85ad2e028f..b273dc2c89 100644 --- a/old-makefile +++ b/old-makefile @@ -115,6 +115,7 @@ SOURCES-$(SNDIO) += audio/out/ao_sndio.c SOURCES-$(VDPAU) += video/vdpau.c video/out/vo_vdpau.c SOURCES-$(VDPAU_GL_X11) += video/out/gl_hwdec_vdpau.c SOURCES-$(VDA) += video/decode/vda.c +SOURCES-$(VDA_GL) += video/out/gl_hwdec_vda.c SOURCES-$(VDPAU_DEC) += video/decode/vdpau.c SOURCES-$(VDPAU_DEC_OLD) += video/decode/vdpau_old.c SOURCES-$(VAAPI) += video/out/vo_vaapi.c \ diff --git a/video/decode/vda.c b/video/decode/vda.c index 2aba19111f..c20bdc9b5f 100644 --- a/video/decode/vda.c +++ b/video/decode/vda.c @@ -88,6 +88,8 @@ static void print_vda_error(int lev, char *message, int error_code) static int probe(struct vd_lavc_hwdec *hwdec, struct mp_hwdec_info *info, const char *decoder) { + hwdec_request_api(info, "vda"); + if (!find_codec(mp_codec_to_av_codec_id(decoder), FF_PROFILE_UNKNOWN)) return HWDEC_ERR_NO_CODEC; return 0; @@ -107,6 +109,7 @@ static int init_vda_decoder(struct lavc_ctx *ctx) .width = ctx->avctx->width, .height = ctx->avctx->height, .format = pe->vda_codec, + // equals to k2vuyPixelFormat (= YUY2/UYVY) .cv_pix_fmt_type = kCVPixelFormatType_422YpCbCr8, #if HAVE_VDA_LIBAVCODEC_REFCOUNTING 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); @@ -635,6 +635,11 @@ hwaccel_features = [ """struct vda_context a = (struct vda_context) { .use_ref_buffer = 1 }""", use='libav') }, { + 'name': '--vda-gl', + 'desc': 'VDA with OpenGL', + 'deps': [ 'gl-cocoa', 'vda-hwaccel' ], + 'func': check_true + }, { 'name': '--vdpau-decoder', 'desc': 'VDPAU decoder (old)', 'deps': [ 'vdpau' ], diff --git a/wscript_build.py b/wscript_build.py index b7e03b92cc..0a5920e67e 100644 --- a/wscript_build.py +++ b/wscript_build.py @@ -335,6 +335,7 @@ def build(ctx): ( "video/out/gl_cocoa.c", "gl-cocoa" ), ( "video/out/gl_common.c", "gl" ), ( "video/out/gl_hwdec_vaglx.c", "vaapi-glx" ), + ( "video/out/gl_hwdec_vda.c", "vda-gl" ), ( "video/out/gl_hwdec_vdpau.c", "vdpau-gl-x11" ), ( "video/out/gl_lcms.c", "gl" ), ( "video/out/gl_osd.c", "gl" ), |