From 3b236d176dbebddad6fcbae74d0990ecfb0412d0 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 1 Aug 2013 08:28:16 +0200 Subject: vo_corevideo: move to C from Objective-C This file was alredy written in C. The only remaining part was the file exension and `#import`s. --- Makefile | 2 +- video/out/vo_corevideo.c | 401 ++++++++++++++++++++++++++++++++++++++++++++++ video/out/vo_corevideo.h | 28 ---- video/out/vo_corevideo.m | 403 ----------------------------------------------- 4 files changed, 402 insertions(+), 432 deletions(-) create mode 100644 video/out/vo_corevideo.c delete mode 100644 video/out/vo_corevideo.h delete mode 100644 video/out/vo_corevideo.m diff --git a/Makefile b/Makefile index d28390b4ba..12c078f77f 100644 --- a/Makefile +++ b/Makefile @@ -76,7 +76,7 @@ SOURCES-$(SDL2) += video/out/vo_sdl.c SOURCES-$(COREAUDIO) += audio/out/ao_coreaudio.c \ audio/out/ao_coreaudio_utils.c \ audio/out/ao_coreaudio_properties.c -SOURCES-$(COREVIDEO) += video/out/vo_corevideo.m +SOURCES-$(COREVIDEO) += video/out/vo_corevideo.c SOURCES-$(DIRECT3D) += video/out/vo_direct3d.c \ video/out/w32_common.c SOURCES-$(DSOUND) += audio/out/ao_dsound.c diff --git a/video/out/vo_corevideo.c b/video/out/vo_corevideo.c new file mode 100644 index 0000000000..cf89dc78c2 --- /dev/null +++ b/video/out/vo_corevideo.c @@ -0,0 +1,401 @@ +/* + * CoreVideo video output driver + * Copyright (c) 2005 Nicolas Plourde + * + * This file is part of MPlayer. + * + * MPlayer 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. + * + * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include + +#include "talloc.h" +#include "video/out/vo.h" +#include "sub/sub.h" +#include "core/m_option.h" + +#include "video/csputils.h" +#include "video/vfcap.h" +#include "video/mp_image.h" + +#include "gl_common.h" +#include "gl_osd.h" +#include "cocoa_common.h" + +struct quad { + GLfloat lowerLeft[2]; + GLfloat lowerRight[2]; + GLfloat upperRight[2]; + GLfloat upperLeft[2]; +}; + +struct priv { + MPGLContext *mpglctx; + OSType pixelFormat; + unsigned int image_width; + unsigned int image_height; + struct mp_csp_details colorspace; + struct mp_rect src_rect; + struct mp_rect dst_rect; + struct mp_osd_res osd_res; + + CVPixelBufferRef pixelBuffer; + CVOpenGLTextureCacheRef textureCache; + CVOpenGLTextureRef texture; + struct quad *quad; + + struct mpgl_osd *osd; +}; + +static void resize(struct vo *vo) +{ + struct priv *p = vo->priv; + GL *gl = p->mpglctx->gl; + + gl->Viewport(0, 0, vo->dwidth, vo->dheight); + gl->MatrixMode(GL_MODELVIEW); + gl->LoadIdentity(); + gl->Ortho(0, vo->dwidth, vo->dheight, 0, -1, 1); + + vo_get_src_dst_rects(vo, &p->src_rect, &p->dst_rect, &p->osd_res); + + gl->Clear(GL_COLOR_BUFFER_BIT); + vo->want_redraw = true; +} + +static int init_gl(struct vo *vo, uint32_t d_width, uint32_t d_height) +{ + struct priv *p = vo->priv; + GL *gl = p->mpglctx->gl; + + const char *vendor = gl->GetString(GL_VENDOR); + const char *version = gl->GetString(GL_VERSION); + const char *renderer = gl->GetString(GL_RENDERER); + + mp_msg(MSGT_VO, MSGL_V, "[vo_corevideo] Running on OpenGL '%s' by '%s'," + " version '%s'\n", renderer, vendor, version); + + gl->Disable(GL_BLEND); + gl->Disable(GL_DEPTH_TEST); + gl->DepthMask(GL_FALSE); + gl->Disable(GL_CULL_FACE); + gl->Enable(GL_TEXTURE_2D); + gl->DrawBuffer(GL_BACK); + gl->TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + + if (!p->osd) + p->osd = mpgl_osd_init(gl, true); + + resize(vo); + + gl->ClearColor(0.0f, 0.0f, 0.0f, 0.0f); + gl->Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + if (gl->SwapInterval) + gl->SwapInterval(1); + return 1; +} + +static void release_cv_entities(struct vo *vo) { + struct priv *p = vo->priv; + CVPixelBufferRelease(p->pixelBuffer); + p->pixelBuffer = NULL; + CVOpenGLTextureRelease(p->texture); + p->texture = NULL; + CVOpenGLTextureCacheRelease(p->textureCache); + p->textureCache = NULL; +} + +static int config(struct vo *vo, uint32_t width, uint32_t height, + uint32_t d_width, uint32_t d_height, uint32_t flags, + uint32_t format) +{ + struct priv *p = vo->priv; + release_cv_entities(vo); + p->image_width = width; + p->image_height = height; + + int mpgl_caps = MPGL_CAP_GL_LEGACY; + if (!mpgl_config_window(p->mpglctx, mpgl_caps, d_width, d_height, flags)) + return -1; + + init_gl(vo, vo->dwidth, vo->dheight); + + return 0; +} + +static void prepare_texture(struct vo *vo) +{ + struct priv *p = vo->priv; + struct quad *q = p->quad; + CVReturn error; + + CVOpenGLTextureRelease(p->texture); + error = CVOpenGLTextureCacheCreateTextureFromImage(NULL, + p->textureCache, p->pixelBuffer, 0, &p->texture); + if(error != kCVReturnSuccess) + mp_msg(MSGT_VO, MSGL_ERR,"[vo_corevideo] Failed to create OpenGL" + " texture(%d)\n", error); + + CVOpenGLTextureGetCleanTexCoords(p->texture, q->lowerLeft, q->lowerRight, + q->upperRight, q->upperLeft); +} + +// map x/y (in range 0..1) to the video texture, and emit OpenGL vertexes +static void video_vertex(struct vo *vo, float x, float y) +{ + struct priv *p = vo->priv; + struct quad *q = p->quad; + GL *gl = p->mpglctx->gl; + + double tx0 = q->upperLeft[0]; + double ty0 = q->upperLeft[1]; + double tw = q->lowerRight[0] - tx0; + double th = q->lowerRight[1] - ty0; + + double sx0 = p->src_rect.x0 / (double)p->image_width; + double sy0 = p->src_rect.y0 / (double)p->image_height; + double sw = (p->src_rect.x1 - p->src_rect.x0) / (double)p->image_width; + double sh = (p->src_rect.y1 - p->src_rect.y0) / (double)p->image_height; + + gl->TexCoord2f(tx0 + (sx0 + x * sw) * tw, + ty0 + (sy0 + y * sh) * th); + gl->Vertex2f(p->dst_rect.x1 * x + p->dst_rect.x0 * (1 - x), + p->dst_rect.y1 * y + p->dst_rect.y0 * (1 - y)); +} + +static void do_render(struct vo *vo) +{ + struct priv *p = vo->priv; + GL *gl = p->mpglctx->gl; + prepare_texture(vo); + + gl->Enable(CVOpenGLTextureGetTarget(p->texture)); + gl->BindTexture( + CVOpenGLTextureGetTarget(p->texture), + CVOpenGLTextureGetName(p->texture)); + + gl->Begin(GL_QUADS); + video_vertex(vo, 0, 0); + video_vertex(vo, 0, 1); + video_vertex(vo, 1, 1); + video_vertex(vo, 1, 0); + gl->End(); + + gl->Disable(CVOpenGLTextureGetTarget(p->texture)); +} + +static void flip_page(struct vo *vo) +{ + struct priv *p = vo->priv; + p->mpglctx->swapGlBuffers(p->mpglctx); + p->mpglctx->gl->Clear(GL_COLOR_BUFFER_BIT); +} + +static void draw_image(struct vo *vo, mp_image_t *mpi) +{ + struct priv *p = vo->priv; + CVReturn error; + + if (!p->textureCache || !p->pixelBuffer) { + error = CVOpenGLTextureCacheCreate(NULL, 0, vo_cocoa_cgl_context(vo), + vo_cocoa_cgl_pixel_format(vo), 0, &p->textureCache); + if(error != kCVReturnSuccess) + mp_msg(MSGT_VO, MSGL_ERR,"[vo_corevideo] Failed to create OpenGL" + " texture Cache(%d)\n", error); + + error = CVPixelBufferCreateWithBytes(NULL, mpi->w, mpi->h, + p->pixelFormat, mpi->planes[0], mpi->stride[0], + NULL, NULL, NULL, &p->pixelBuffer); + if(error != kCVReturnSuccess) + mp_msg(MSGT_VO, MSGL_ERR,"[vo_corevideo] Failed to create Pixel" + "Buffer(%d)\n", error); + } + + do_render(vo); +} + +static int query_format(struct vo *vo, uint32_t format) +{ + struct priv *p = vo->priv; + const int flags = VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW; + switch (format) { + case IMGFMT_YUYV: + p->pixelFormat = kYUVSPixelFormat; + return flags; + + case IMGFMT_RGB24: + p->pixelFormat = k24RGBPixelFormat; + return flags; + + case IMGFMT_ARGB: + p->pixelFormat = k32ARGBPixelFormat; + return flags; + + case IMGFMT_BGRA: + p->pixelFormat = k32BGRAPixelFormat; + return flags; + } + return 0; +} + +static void uninit(struct vo *vo) +{ + struct priv *p = vo->priv; + if (p->osd) + mpgl_osd_destroy(p->osd); + release_cv_entities(vo); + mpgl_uninit(p->mpglctx); +} + + +static int preinit(struct vo *vo) +{ + struct priv *p = vo->priv; + + *p = (struct priv) { + .mpglctx = mpgl_init(vo, "cocoa"), + .colorspace = MP_CSP_DETAILS_DEFAULTS, + .quad = talloc_ptrtype(p, p->quad), + }; + + return 0; +} + +static void draw_osd(struct vo *vo, struct osd_state *osd) +{ + struct priv *p = vo->priv; + assert(p->osd); + + mpgl_osd_draw_legacy(p->osd, osd, p->osd_res); +} + +static CFStringRef get_cv_csp_matrix(struct vo *vo) +{ + struct priv *p = vo->priv; + switch (p->colorspace.format) { + case MP_CSP_BT_601: + return kCVImageBufferYCbCrMatrix_ITU_R_601_4; + case MP_CSP_BT_709: + return kCVImageBufferYCbCrMatrix_ITU_R_709_2; + case MP_CSP_SMPTE_240M: + return kCVImageBufferYCbCrMatrix_SMPTE_240M_1995; + default: + return kCVImageBufferYCbCrMatrix_ITU_R_601_4; + } +} + +static void set_yuv_colorspace(struct vo *vo) +{ + struct priv *p = vo->priv; + CVBufferSetAttachment(p->pixelBuffer, + kCVImageBufferYCbCrMatrixKey, get_cv_csp_matrix(vo), + kCVAttachmentMode_ShouldPropagate); + vo->want_redraw = true; +} + +static int get_image_fmt(struct vo *vo) +{ + struct priv *p = vo->priv; + switch (p->pixelFormat) { + case kYUVSPixelFormat: return IMGFMT_YUYV; + case k24RGBPixelFormat: return IMGFMT_RGB24; + case k32ARGBPixelFormat: return IMGFMT_ARGB; + case k32BGRAPixelFormat: return IMGFMT_BGRA; + } + mp_msg(MSGT_VO, MSGL_ERR, "[vo_corevideo] Failed to convert pixel format. " + "Please contact the developers. PixelFormat: %d\n", p->pixelFormat); + return -1; +} + +static mp_image_t *get_screenshot(struct vo *vo) +{ + int img_fmt = get_image_fmt(vo); + if (img_fmt < 0) return NULL; + + struct priv *p = vo->priv; + void *base = CVPixelBufferGetBaseAddress(p->pixelBuffer); + + size_t width = CVPixelBufferGetWidth(p->pixelBuffer); + size_t height = CVPixelBufferGetHeight(p->pixelBuffer); + size_t stride = CVPixelBufferGetBytesPerRow(p->pixelBuffer); + + struct mp_image img = {0}; + mp_image_setfmt(&img, img_fmt); + mp_image_set_size(&img, width, height); + img.planes[0] = base; + img.stride[0] = stride; + + struct mp_image *image = mp_image_new_copy(&img); + mp_image_set_display_size(image, vo->aspdat.prew, vo->aspdat.preh); + mp_image_set_colorspace_details(image, &p->colorspace); + + return image; +} + +static int control(struct vo *vo, uint32_t request, void *data) +{ + struct priv *p = vo->priv; + switch (request) { + case VOCTRL_GET_PANSCAN: + return VO_TRUE; + case VOCTRL_SET_PANSCAN: + resize(vo); + return VO_TRUE; + case VOCTRL_REDRAW_FRAME: + do_render(vo); + return VO_TRUE; + case VOCTRL_SET_YUV_COLORSPACE: + p->colorspace.format = ((struct mp_csp_details *)data)->format; + set_yuv_colorspace(vo); + return VO_TRUE; + case VOCTRL_GET_YUV_COLORSPACE: + *(struct mp_csp_details *)data = p->colorspace; + return VO_TRUE; + case VOCTRL_SCREENSHOT: { + struct voctrl_screenshot_args *args = data; + if (args->full_window) + args->out_image = glGetWindowScreenshot(p->mpglctx->gl); + else + args->out_image = get_screenshot(vo); + return VO_TRUE; + } + } + + int events = 0; + int r = p->mpglctx->vo_control(vo, &events, request, data); + if (events & VO_EVENT_RESIZE) + resize(vo); + + return r; +} + +const struct vo_driver video_out_corevideo = { + .info = &(const vo_info_t) { + "Mac OS X Core Video", + "corevideo", + "Nicolas Plourde and others", + "" + }, + .preinit = preinit, + .query_format = query_format, + .config = config, + .control = control, + .draw_image = draw_image, + .draw_osd = draw_osd, + .flip_page = flip_page, + .uninit = uninit, + .priv_size = sizeof(struct priv), +}; diff --git a/video/out/vo_corevideo.h b/video/out/vo_corevideo.h deleted file mode 100644 index cfb86621bc..0000000000 --- a/video/out/vo_corevideo.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * CoreVideo video output driver - * - * Copyright (c) 2005 Nicolas Plourde - * - * This file is part of MPlayer. - * - * MPlayer 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. - * - * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef MPLAYER_VO_COREVIDEO_H -#define MPLAYER_VO_COREVIDEO_H - -#import - -#endif /* MPLAYER_VO_COREVIDEO_H */ diff --git a/video/out/vo_corevideo.m b/video/out/vo_corevideo.m deleted file mode 100644 index cb60fef95d..0000000000 --- a/video/out/vo_corevideo.m +++ /dev/null @@ -1,403 +0,0 @@ -/* - * CoreVideo video output driver - * Copyright (c) 2005 Nicolas Plourde - * - * This file is part of MPlayer. - * - * MPlayer 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. - * - * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include - -#import "vo_corevideo.h" - -// mplayer includes -#import "talloc.h" -#import "vo.h" -#import "sub/sub.h" -#import "core/m_option.h" - -#import "video/csputils.h" -#import "video/vfcap.h" -#import "video/mp_image.h" - -#import "gl_common.h" -#import "gl_osd.h" -#import "cocoa_common.h" - -struct quad { - GLfloat lowerLeft[2]; - GLfloat lowerRight[2]; - GLfloat upperRight[2]; - GLfloat upperLeft[2]; -}; - -struct priv { - MPGLContext *mpglctx; - OSType pixelFormat; - unsigned int image_width; - unsigned int image_height; - struct mp_csp_details colorspace; - struct mp_rect src_rect; - struct mp_rect dst_rect; - struct mp_osd_res osd_res; - - CVPixelBufferRef pixelBuffer; - CVOpenGLTextureCacheRef textureCache; - CVOpenGLTextureRef texture; - struct quad *quad; - - struct mpgl_osd *osd; -}; - -static void resize(struct vo *vo) -{ - struct priv *p = vo->priv; - GL *gl = p->mpglctx->gl; - - gl->Viewport(0, 0, vo->dwidth, vo->dheight); - gl->MatrixMode(GL_MODELVIEW); - gl->LoadIdentity(); - gl->Ortho(0, vo->dwidth, vo->dheight, 0, -1, 1); - - vo_get_src_dst_rects(vo, &p->src_rect, &p->dst_rect, &p->osd_res); - - gl->Clear(GL_COLOR_BUFFER_BIT); - vo->want_redraw = true; -} - -static int init_gl(struct vo *vo, uint32_t d_width, uint32_t d_height) -{ - struct priv *p = vo->priv; - GL *gl = p->mpglctx->gl; - - const char *vendor = gl->GetString(GL_VENDOR); - const char *version = gl->GetString(GL_VERSION); - const char *renderer = gl->GetString(GL_RENDERER); - - mp_msg(MSGT_VO, MSGL_V, "[vo_corevideo] Running on OpenGL '%s' by '%s'," - " version '%s'\n", renderer, vendor, version); - - gl->Disable(GL_BLEND); - gl->Disable(GL_DEPTH_TEST); - gl->DepthMask(GL_FALSE); - gl->Disable(GL_CULL_FACE); - gl->Enable(GL_TEXTURE_2D); - gl->DrawBuffer(GL_BACK); - gl->TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - - if (!p->osd) - p->osd = mpgl_osd_init(gl, true); - - resize(vo); - - gl->ClearColor(0.0f, 0.0f, 0.0f, 0.0f); - gl->Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - if (gl->SwapInterval) - gl->SwapInterval(1); - return 1; -} - -static void release_cv_entities(struct vo *vo) { - struct priv *p = vo->priv; - CVPixelBufferRelease(p->pixelBuffer); - p->pixelBuffer = NULL; - CVOpenGLTextureRelease(p->texture); - p->texture = NULL; - CVOpenGLTextureCacheRelease(p->textureCache); - p->textureCache = NULL; -} - -static int config(struct vo *vo, uint32_t width, uint32_t height, - uint32_t d_width, uint32_t d_height, uint32_t flags, - uint32_t format) -{ - struct priv *p = vo->priv; - release_cv_entities(vo); - p->image_width = width; - p->image_height = height; - - int mpgl_caps = MPGL_CAP_GL_LEGACY; - if (!mpgl_config_window(p->mpglctx, mpgl_caps, d_width, d_height, flags)) - return -1; - - init_gl(vo, vo->dwidth, vo->dheight); - - return 0; -} - -static void prepare_texture(struct vo *vo) -{ - struct priv *p = vo->priv; - struct quad *q = p->quad; - CVReturn error; - - CVOpenGLTextureRelease(p->texture); - error = CVOpenGLTextureCacheCreateTextureFromImage(NULL, - p->textureCache, p->pixelBuffer, 0, &p->texture); - if(error != kCVReturnSuccess) - mp_msg(MSGT_VO, MSGL_ERR,"[vo_corevideo] Failed to create OpenGL" - " texture(%d)\n", error); - - CVOpenGLTextureGetCleanTexCoords(p->texture, q->lowerLeft, q->lowerRight, - q->upperRight, q->upperLeft); -} - -// map x/y (in range 0..1) to the video texture, and emit OpenGL vertexes -static void video_vertex(struct vo *vo, float x, float y) -{ - struct priv *p = vo->priv; - struct quad *q = p->quad; - GL *gl = p->mpglctx->gl; - - double tx0 = q->upperLeft[0]; - double ty0 = q->upperLeft[1]; - double tw = q->lowerRight[0] - tx0; - double th = q->lowerRight[1] - ty0; - - double sx0 = p->src_rect.x0 / (double)p->image_width; - double sy0 = p->src_rect.y0 / (double)p->image_height; - double sw = (p->src_rect.x1 - p->src_rect.x0) / (double)p->image_width; - double sh = (p->src_rect.y1 - p->src_rect.y0) / (double)p->image_height; - - gl->TexCoord2f(tx0 + (sx0 + x * sw) * tw, - ty0 + (sy0 + y * sh) * th); - gl->Vertex2f(p->dst_rect.x1 * x + p->dst_rect.x0 * (1 - x), - p->dst_rect.y1 * y + p->dst_rect.y0 * (1 - y)); -} - -static void do_render(struct vo *vo) -{ - struct priv *p = vo->priv; - GL *gl = p->mpglctx->gl; - prepare_texture(vo); - - gl->Enable(CVOpenGLTextureGetTarget(p->texture)); - gl->BindTexture( - CVOpenGLTextureGetTarget(p->texture), - CVOpenGLTextureGetName(p->texture)); - - gl->Begin(GL_QUADS); - video_vertex(vo, 0, 0); - video_vertex(vo, 0, 1); - video_vertex(vo, 1, 1); - video_vertex(vo, 1, 0); - gl->End(); - - gl->Disable(CVOpenGLTextureGetTarget(p->texture)); -} - -static void flip_page(struct vo *vo) -{ - struct priv *p = vo->priv; - p->mpglctx->swapGlBuffers(p->mpglctx); - p->mpglctx->gl->Clear(GL_COLOR_BUFFER_BIT); -} - -static void draw_image(struct vo *vo, mp_image_t *mpi) -{ - struct priv *p = vo->priv; - CVReturn error; - - if (!p->textureCache || !p->pixelBuffer) { - error = CVOpenGLTextureCacheCreate(NULL, 0, vo_cocoa_cgl_context(vo), - vo_cocoa_cgl_pixel_format(vo), 0, &p->textureCache); - if(error != kCVReturnSuccess) - mp_msg(MSGT_VO, MSGL_ERR,"[vo_corevideo] Failed to create OpenGL" - " texture Cache(%d)\n", error); - - error = CVPixelBufferCreateWithBytes(NULL, mpi->w, mpi->h, - p->pixelFormat, mpi->planes[0], mpi->stride[0], - NULL, NULL, NULL, &p->pixelBuffer); - if(error != kCVReturnSuccess) - mp_msg(MSGT_VO, MSGL_ERR,"[vo_corevideo] Failed to create Pixel" - "Buffer(%d)\n", error); - } - - do_render(vo); -} - -static int query_format(struct vo *vo, uint32_t format) -{ - struct priv *p = vo->priv; - const int flags = VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW; - switch (format) { - case IMGFMT_YUYV: - p->pixelFormat = kYUVSPixelFormat; - return flags; - - case IMGFMT_RGB24: - p->pixelFormat = k24RGBPixelFormat; - return flags; - - case IMGFMT_ARGB: - p->pixelFormat = k32ARGBPixelFormat; - return flags; - - case IMGFMT_BGRA: - p->pixelFormat = k32BGRAPixelFormat; - return flags; - } - return 0; -} - -static void uninit(struct vo *vo) -{ - struct priv *p = vo->priv; - if (p->osd) - mpgl_osd_destroy(p->osd); - release_cv_entities(vo); - mpgl_uninit(p->mpglctx); -} - - -static int preinit(struct vo *vo) -{ - struct priv *p = vo->priv; - - *p = (struct priv) { - .mpglctx = mpgl_init(vo, "cocoa"), - .colorspace = MP_CSP_DETAILS_DEFAULTS, - .quad = talloc_ptrtype(p, p->quad), - }; - - return 0; -} - -static void draw_osd(struct vo *vo, struct osd_state *osd) -{ - struct priv *p = vo->priv; - assert(p->osd); - - mpgl_osd_draw_legacy(p->osd, osd, p->osd_res); -} - -static CFStringRef get_cv_csp_matrix(struct vo *vo) -{ - struct priv *p = vo->priv; - switch (p->colorspace.format) { - case MP_CSP_BT_601: - return kCVImageBufferYCbCrMatrix_ITU_R_601_4; - case MP_CSP_BT_709: - return kCVImageBufferYCbCrMatrix_ITU_R_709_2; - case MP_CSP_SMPTE_240M: - return kCVImageBufferYCbCrMatrix_SMPTE_240M_1995; - default: - return kCVImageBufferYCbCrMatrix_ITU_R_601_4; - } -} - -static void set_yuv_colorspace(struct vo *vo) -{ - struct priv *p = vo->priv; - CVBufferSetAttachment(p->pixelBuffer, - kCVImageBufferYCbCrMatrixKey, get_cv_csp_matrix(vo), - kCVAttachmentMode_ShouldPropagate); - vo->want_redraw = true; -} - -static int get_image_fmt(struct vo *vo) -{ - struct priv *p = vo->priv; - switch (p->pixelFormat) { - case kYUVSPixelFormat: return IMGFMT_YUYV; - case k24RGBPixelFormat: return IMGFMT_RGB24; - case k32ARGBPixelFormat: return IMGFMT_ARGB; - case k32BGRAPixelFormat: return IMGFMT_BGRA; - } - mp_msg(MSGT_VO, MSGL_ERR, "[vo_corevideo] Failed to convert pixel format. " - "Please contact the developers. PixelFormat: %d\n", p->pixelFormat); - return -1; -} - -static mp_image_t *get_screenshot(struct vo *vo) -{ - int img_fmt = get_image_fmt(vo); - if (img_fmt < 0) return NULL; - - struct priv *p = vo->priv; - void *base = CVPixelBufferGetBaseAddress(p->pixelBuffer); - - size_t width = CVPixelBufferGetWidth(p->pixelBuffer); - size_t height = CVPixelBufferGetHeight(p->pixelBuffer); - size_t stride = CVPixelBufferGetBytesPerRow(p->pixelBuffer); - - struct mp_image img = {0}; - mp_image_setfmt(&img, img_fmt); - mp_image_set_size(&img, width, height); - img.planes[0] = base; - img.stride[0] = stride; - - struct mp_image *image = mp_image_new_copy(&img); - mp_image_set_display_size(image, vo->aspdat.prew, vo->aspdat.preh); - mp_image_set_colorspace_details(image, &p->colorspace); - - return image; -} - -static int control(struct vo *vo, uint32_t request, void *data) -{ - struct priv *p = vo->priv; - switch (request) { - case VOCTRL_GET_PANSCAN: - return VO_TRUE; - case VOCTRL_SET_PANSCAN: - resize(vo); - return VO_TRUE; - case VOCTRL_REDRAW_FRAME: - do_render(vo); - return VO_TRUE; - case VOCTRL_SET_YUV_COLORSPACE: - p->colorspace.format = ((struct mp_csp_details *)data)->format; - set_yuv_colorspace(vo); - return VO_TRUE; - case VOCTRL_GET_YUV_COLORSPACE: - *(struct mp_csp_details *)data = p->colorspace; - return VO_TRUE; - case VOCTRL_SCREENSHOT: { - struct voctrl_screenshot_args *args = data; - if (args->full_window) - args->out_image = glGetWindowScreenshot(p->mpglctx->gl); - else - args->out_image = get_screenshot(vo); - return VO_TRUE; - } - } - - int events = 0; - int r = p->mpglctx->vo_control(vo, &events, request, data); - if (events & VO_EVENT_RESIZE) - resize(vo); - - return r; -} - -const struct vo_driver video_out_corevideo = { - .info = &(const vo_info_t) { - "Mac OS X Core Video", - "corevideo", - "Nicolas Plourde and others", - "" - }, - .preinit = preinit, - .query_format = query_format, - .config = config, - .control = control, - .draw_image = draw_image, - .draw_osd = draw_osd, - .flip_page = flip_page, - .uninit = uninit, - .priv_size = sizeof(struct priv), -}; -- cgit v1.2.3