diff --git a/libvo/gl_common.c b/libvo/gl_common.c index 3031dc5967..055b386639 100644 --- a/libvo/gl_common.c +++ b/libvo/gl_common.c @@ -1965,6 +1965,24 @@ void glDrawTex(GL *gl, GLfloat x, GLfloat y, GLfloat w, GLfloat h, gl->End(); } +mp_image_t *glGetWindowScreenshot(GL *gl) +{ + GLint vp[4]; //x, y, w, h + gl->GetIntegerv(GL_VIEWPORT, vp); + mp_image_t *image = alloc_mpi(vp[2], vp[3], IMGFMT_RGB24); + gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + gl->PixelStorei(GL_PACK_ALIGNMENT, 0); + gl->PixelStorei(GL_PACK_ROW_LENGTH, 0); + gl->ReadBuffer(GL_FRONT); + //flip image while reading + for (int y = 0; y < vp[3]; y++) { + gl->ReadPixels(vp[0], vp[1] + vp[3] - y - 1, vp[2], 1, + GL_RGB, GL_UNSIGNED_BYTE, + image->planes[0] + y * image->stride[0]); + } + return image; +} + #ifdef CONFIG_GL_COCOA #include "cocoa_common.h" diff --git a/libvo/gl_common.h b/libvo/gl_common.h index fd80b69126..d9f227c6aa 100644 --- a/libvo/gl_common.h +++ b/libvo/gl_common.h @@ -33,6 +33,8 @@ #include "video_out.h" #include "csputils.h" +#include "libmpcodecs/mp_image.h" + #if defined(CONFIG_GL_COCOA) && !defined(CONFIG_GL_X11) #ifdef GL_VERSION_3_0 #include @@ -72,6 +74,7 @@ void glDrawTex(GL *gl, GLfloat x, GLfloat y, GLfloat w, GLfloat h, int sx, int sy, int rect_tex, int is_yv12, int flip); int loadGPUProgram(GL *gl, GLenum target, char *prog); void glCheckError(GL *gl, const char *info); +mp_image_t *glGetWindowScreenshot(GL *gl); /** \addtogroup glconversion * \{ */ diff --git a/libvo/vo_corevideo.m b/libvo/vo_corevideo.m index 06010cad49..fb9350cc47 100644 --- a/libvo/vo_corevideo.m +++ b/libvo/vo_corevideo.m @@ -344,6 +344,46 @@ static void set_yuv_colorspace(struct vo *vo) vo->want_redraw = true; } +static int get_image_fmt(struct vo *vo) +{ + struct priv *p = vo->priv; + switch (p->pixelFormat) { + case kYUVSPixelFormat: return IMGFMT_YUY2; + 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); + size_t image_size = stride * height; + + mp_image_t *image = alloc_mpi(width, height, img_fmt); + memcpy(image->planes[0], base, image_size); + image->stride[0] = stride; + + image->width = width; + image->height = height; + + image->w = vo->aspdat.prew; + image->h = vo->aspdat.preh; + + return image; +} + static int control(struct vo *vo, uint32_t request, void *data) { struct priv *p = vo->priv; @@ -377,6 +417,14 @@ static int control(struct vo *vo, uint32_t request, void *data) 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; + } } return VO_NOTIMPL; } diff --git a/libvo/vo_opengl.c b/libvo/vo_opengl.c index df82a239d1..8b1b6aaa35 100644 --- a/libvo/vo_opengl.c +++ b/libvo/vo_opengl.c @@ -1403,23 +1403,6 @@ static mp_image_t *get_screenshot(struct gl_priv *p) return image; } -static mp_image_t *get_window_screenshot(struct gl_priv *p) -{ - GL *gl = p->gl; - - mp_image_t *image = alloc_mpi(p->vp_w, p->vp_h, IMGFMT_RGB24); - gl->PixelStorei(GL_PACK_ALIGNMENT, 4); - gl->PixelStorei(GL_PACK_ROW_LENGTH, 0); - gl->ReadBuffer(GL_FRONT); - // flip image while reading - for (int y = 0; y < p->vp_h; y++) { - gl->ReadPixels(p->vp_x, p->vp_y + p->vp_h - y - 1, p->vp_w, 1, - GL_RGB, GL_UNSIGNED_BYTE, - image->planes[0] + y * image->stride[0]); - } - return image; -} - static void draw_osd_cb(void *ctx, struct sub_bitmaps *imgs) { struct gl_priv *p = ctx; @@ -1842,7 +1825,7 @@ static int control(struct vo *vo, uint32_t request, void *data) case VOCTRL_SCREENSHOT: { struct voctrl_screenshot_args *args = data; if (args->full_window) - args->out_image = get_window_screenshot(p); + args->out_image = glGetWindowScreenshot(p->gl); else args->out_image = get_screenshot(p); return true; diff --git a/libvo/vo_opengl_old.c b/libvo/vo_opengl_old.c index ac104a3cde..e83d45a692 100644 --- a/libvo/vo_opengl_old.c +++ b/libvo/vo_opengl_old.c @@ -835,27 +835,6 @@ static mp_image_t *get_screenshot(struct vo *vo) return image; } -static mp_image_t *get_window_screenshot(struct vo *vo) -{ - struct gl_priv *p = vo->priv; - GL *gl = p->gl; - - GLint vp[4]; //x, y, w, h - gl->GetIntegerv(GL_VIEWPORT, vp); - mp_image_t *image = alloc_mpi(vp[2], vp[3], IMGFMT_RGB24); - gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); - gl->PixelStorei(GL_PACK_ALIGNMENT, 0); - gl->PixelStorei(GL_PACK_ROW_LENGTH, 0); - gl->ReadBuffer(GL_FRONT); - //flip image while reading - for (int y = 0; y < vp[3]; y++) { - gl->ReadPixels(vp[0], vp[1] + vp[3] - y - 1, vp[2], 1, - GL_RGB, GL_UNSIGNED_BYTE, - image->planes[0] + y * image->stride[0]); - } - return image; -} - static int query_format(struct vo *vo, uint32_t format) { struct gl_priv *p = vo->priv; @@ -1158,7 +1137,7 @@ static int control(struct vo *vo, uint32_t request, void *data) case VOCTRL_SCREENSHOT: { struct voctrl_screenshot_args *args = data; if (args->full_window) - args->out_image = get_window_screenshot(vo); + args->out_image = glGetWindowScreenshot(p->gl); else args->out_image = get_screenshot(vo); return true;