summaryrefslogtreecommitdiffstats
path: root/libvo/vo_corevideo.m
diff options
context:
space:
mode:
Diffstat (limited to 'libvo/vo_corevideo.m')
-rw-r--r--libvo/vo_corevideo.m203
1 files changed, 91 insertions, 112 deletions
diff --git a/libvo/vo_corevideo.m b/libvo/vo_corevideo.m
index 0db161fd18..5116ab653c 100644
--- a/libvo/vo_corevideo.m
+++ b/libvo/vo_corevideo.m
@@ -19,6 +19,8 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+#include <assert.h>
+
#import "vo_corevideo.h"
// mplayer includes
@@ -32,9 +34,9 @@
#import "csputils.h"
#import "libmpcodecs/vfcap.h"
#import "libmpcodecs/mp_image.h"
-#import "osd.h"
#import "gl_common.h"
+#import "gl_osd.h"
#import "cocoa_common.h"
struct quad {
@@ -44,44 +46,31 @@ struct quad {
GLfloat upperLeft[2];
};
-#define CV_VERTICES_PER_QUAD 6
-#define CV_MAX_OSD_PARTS 20
-
-struct osd_p {
- GLuint tex[CV_MAX_OSD_PARTS];
- NSRect tex_rect[CV_MAX_OSD_PARTS];
- int tex_cnt;
-};
-
struct priv {
MPGLContext *mpglctx;
OSType pixelFormat;
unsigned int image_width;
unsigned int image_height;
struct mp_csp_details colorspace;
+ int ass_border_x, ass_border_y;
CVPixelBufferRef pixelBuffer;
CVOpenGLTextureCacheRef textureCache;
CVOpenGLTextureRef texture;
struct quad *quad;
- struct osd_p *osd;
+ struct mpgl_osd *osd;
};
static void resize(struct vo *vo, int width, int height)
{
struct priv *p = vo->priv;
GL *gl = p->mpglctx->gl;
- p->image_width = width;
- p->image_height = height;
-
- mp_msg(MSGT_VO, MSGL_V, "[vo_corevideo] New OpenGL Viewport (0, 0, %d, "
- "%d)\n", p->image_width, p->image_height);
- gl->Viewport(0, 0, p->image_width, p->image_height);
+ gl->Viewport(0, 0, width, height);
gl->MatrixMode(GL_PROJECTION);
gl->LoadIdentity();
-
+ p->ass_border_x = p->ass_border_y = 0;
if (aspect_scaling()) {
int new_w, new_h;
GLdouble scale_x, scale_y;
@@ -90,17 +79,17 @@ static void resize(struct vo *vo, int width, int height)
panscan_calc_windowed(vo);
new_w += vo->panscan_x;
new_h += vo->panscan_y;
- scale_x = (GLdouble)new_w / (GLdouble)p->image_width;
- scale_y = (GLdouble)new_h / (GLdouble)p->image_height;
+ scale_x = (GLdouble)new_w / (GLdouble)width;
+ scale_y = (GLdouble)new_h / (GLdouble)height;
gl->Scaled(scale_x, scale_y, 1);
+ p->ass_border_x = (vo->dwidth - new_w) / 2;
+ p->ass_border_y = (vo->dheight - new_h) / 2;
}
gl->Ortho(0, p->image_width, p->image_height, 0, -1.0, 1.0);
gl->MatrixMode(GL_MODELVIEW);
gl->LoadIdentity();
- vo_osd_resized();
-
gl->Clear(GL_COLOR_BUFFER_BIT);
vo->want_redraw = true;
}
@@ -125,6 +114,9 @@ static int init_gl(struct vo *vo, uint32_t d_width, uint32_t d_height)
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, d_width, d_height);
gl->ClearColor(0.0f, 0.0f, 0.0f, 0.0f);
@@ -142,7 +134,6 @@ static void release_cv_entities(struct vo *vo) {
p->texture = NULL;
CVOpenGLTextureCacheRelease(p->textureCache);
p->textureCache = NULL;
-
}
static int config(struct vo *vo, uint32_t width, uint32_t height,
@@ -171,90 +162,6 @@ static void check_events(struct vo *vo)
resize(vo, vo->dwidth, vo->dheight);
}
-static void create_osd_texture(void *ctx, int x0, int y0, int w, int h,
- unsigned char *src, unsigned char *srca,
- int stride)
-{
- struct priv *p = ((struct vo *) ctx)->priv;
- struct osd_p *osd = p->osd;
- GL *gl = p->mpglctx->gl;
-
- if (w <= 0 || h <= 0 || stride < w) {
- mp_msg(MSGT_VO, MSGL_V, "Invalid dimensions OSD for part!\n");
- return;
- }
-
- if (osd->tex_cnt >= CV_MAX_OSD_PARTS) {
- mp_msg(MSGT_VO, MSGL_ERR, "Too many OSD parts, contact the"
- " developers!\n");
- return;
- }
-
- gl->GenTextures(1, &osd->tex[osd->tex_cnt]);
- gl->BindTexture(GL_TEXTURE_2D, osd->tex[osd->tex_cnt]);
- glCreateClearTex(gl, GL_TEXTURE_2D, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA,
- GL_UNSIGNED_BYTE, GL_LINEAR, w, h, 0);
- {
- int i;
- unsigned char *tmp = malloc(stride * h * 2);
- // convert alpha from weird MPlayer scale.
- for (i = 0; i < h * stride; i++) {
- tmp[i*2+0] = src[i];
- tmp[i*2+1] = -srca[i];
- }
- glUploadTex(gl, GL_TEXTURE_2D, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE,
- tmp, stride * 2, 0, 0, w, h, 0);
- free(tmp);
- }
-
- osd->tex_rect[osd->tex_cnt] = NSMakeRect(x0, y0, w, h);
-
- gl->BindTexture(GL_TEXTURE_2D, 0);
- osd->tex_cnt++;
-}
-
-static void clearOSD(struct vo *vo)
-{
- struct priv *p = vo->priv;
- struct osd_p *osd = p->osd;
- GL *gl = p->mpglctx->gl;
-
- if (!osd->tex_cnt)
- return;
- gl->DeleteTextures(osd->tex_cnt, osd->tex);
- osd->tex_cnt = 0;
-}
-
-static void draw_osd(struct vo *vo, struct osd_state *osd_s)
-{
- struct priv *p = vo->priv;
- struct osd_p *osd = p->osd;
- GL *gl = p->mpglctx->gl;
-
- if (vo_osd_has_changed(osd_s)) {
- clearOSD(vo);
- osd_draw_text_ext(osd_s, vo->dwidth, vo->dheight, 0, 0, 0, 0,
- p->image_width, p->image_height, create_osd_texture,
- vo);
- }
-
- if (osd->tex_cnt > 0) {
- gl->Enable(GL_BLEND);
- gl->BlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
-
- for (int n = 0; n < osd->tex_cnt; n++) {
- NSRect tr = osd->tex_rect[n];
- gl->BindTexture(GL_TEXTURE_2D, osd->tex[n]);
- glDrawTex(gl, tr.origin.x, tr.origin.y,
- tr.size.width, tr.size.height,
- 0, 0, 1.0, 1.0, 1, 1, 0, 0, 0);
- }
-
- gl->Disable(GL_BLEND);
- gl->BindTexture(GL_TEXTURE_2D, 0);
- }
-}
-
static void prepare_texture(struct vo *vo)
{
struct priv *p = vo->priv;
@@ -366,8 +273,10 @@ static int query_format(struct vo *vo, uint32_t format)
static void uninit(struct vo *vo)
{
struct priv *p = vo->priv;
- mpgl_uninit(p->mpglctx);
+ if (p->osd)
+ mpgl_osd_destroy(p->osd);
release_cv_entities(vo);
+ mpgl_uninit(p->mpglctx);
}
@@ -379,14 +288,37 @@ static int preinit(struct vo *vo, const char *arg)
.mpglctx = mpgl_init(GLTYPE_COCOA, vo),
.colorspace = MP_CSP_DETAILS_DEFAULTS,
.quad = talloc_ptrtype(p, p->quad),
- .osd = talloc_ptrtype(p, p->osd),
};
- *p->osd = (struct osd_p) {
- .tex_cnt = 0,
+ return 0;
+}
+
+static void draw_osd(struct vo *vo, struct osd_state *osd)
+{
+ struct priv *p = vo->priv;
+ GL *gl = p->mpglctx->gl;
+ assert(p->osd);
+
+ gl->MatrixMode(GL_PROJECTION);
+ gl->PushMatrix();
+ gl->LoadIdentity();
+ gl->Ortho(0, vo->dwidth, vo->dheight, 0, -1, 1);
+
+ struct mp_osd_res res = {
+ .w = vo->dwidth,
+ .h = vo->dheight,
+ .display_par = vo->monitor_par,
+ .video_par = vo->aspdat.par,
};
- return 0;
+ if (aspect_scaling()) {
+ res.ml = res.mr = p->ass_border_x;
+ res.mt = res.mb = p->ass_border_y;
+ }
+
+ mpgl_osd_draw_legacy(p->osd, osd, res);
+
+ gl->PopMatrix();
}
static CFStringRef get_cv_csp_matrix(struct vo *vo)
@@ -412,6 +344,45 @@ 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->display_w = vo->aspdat.prew;
+ image->display_h = 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;
@@ -455,6 +426,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;
}