vo_corevideo: add screenshot capability

Added screenshot capability to the corevideo VO by sending back the raw data
from the CVPixelBuffer.

Also added "screenshot window" functionality from the other OpenGL based VOs,
which uses glReadPixels to read image data back. This was moved to gl_common to
avoid duplication.
This commit is contained in:
Stefano Pigozzi 2012-10-21 16:25:42 +02:00 committed by wm4
parent 6bea013e27
commit 281989d384
5 changed files with 71 additions and 40 deletions

View File

@ -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"

View File

@ -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 <OpenGL/gl3.h>
@ -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
* \{ */

View File

@ -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;
}

View File

@ -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;

View File

@ -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;