summaryrefslogtreecommitdiffstats
path: root/video/out
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2012-11-05 17:02:04 +0100
committerwm4 <wm4@nowhere>2012-11-12 20:06:14 +0100
commitd4bdd0473d6f43132257c9fb3848d829755167a3 (patch)
tree8021c2f7da1841393c8c832105e20cd527826d6c /video/out
parentbd48deba77bd5582c5829d6fe73a7d2571088aba (diff)
downloadmpv-d4bdd0473d6f43132257c9fb3848d829755167a3.tar.bz2
mpv-d4bdd0473d6f43132257c9fb3848d829755167a3.tar.xz
Rename directories, move files (step 1 of 2) (does not compile)
Tis drops the silly lib prefixes, and attempts to organize the tree in a more logical way. Make the top-level directory less cluttered as well. Renames the following directories: libaf -> audio/filter libao2 -> audio/out libvo -> video/out libmpdemux -> demux Split libmpcodecs: vf* -> video/filter vd*, dec_video.* -> video/decode mp_image*, img_format*, ... -> video/ ad*, dec_audio.* -> audio/decode libaf/format.* is moved to audio/ - this is similar to how mp_image.* is located in video/. Move most top-level .c/.h files to core. (talloc.c/.h is left on top- level, because it's external.) Park some of the more annoying files in compat/. Some of these are relicts from the time mplayer used ffmpeg internals. sub/ is not split, because it's too much of a mess (subtitle code is mixed with OSD display and rendering). Maybe the organization of core is not ideal: it mixes playback core (like mplayer.c) and utility helpers (like bstr.c/h). Should the need arise, the playback core will be moved somewhere else, while core contains all helper and common code.
Diffstat (limited to 'video/out')
-rw-r--r--video/out/aspect.c148
-rw-r--r--video/out/aspect.h37
-rw-r--r--video/out/bitmap_packer.c227
-rw-r--r--video/out/bitmap_packer.h68
-rw-r--r--video/out/cocoa_common.h55
-rw-r--r--video/out/cocoa_common.m865
-rw-r--r--video/out/d3d_shader_yuv.h142
-rw-r--r--video/out/d3d_shader_yuv.hlsl44
-rw-r--r--video/out/d3d_shader_yuv_2ch.h170
-rw-r--r--video/out/filter_kernels.c279
-rw-r--r--video/out/filter_kernels.h45
-rw-r--r--video/out/geometry.c112
-rw-r--r--video/out/geometry.h29
-rw-r--r--video/out/gl_common.c2654
-rw-r--r--video/out/gl_common.h396
-rw-r--r--video/out/gl_header_fixes.h257
-rw-r--r--video/out/gl_osd.c324
-rw-r--r--video/out/gl_osd.h43
-rw-r--r--video/out/osx_common.c145
-rw-r--r--video/out/osx_common.h27
-rw-r--r--video/out/pnm_loader.c97
-rw-r--r--video/out/pnm_loader.h52
-rw-r--r--video/out/vo.c530
-rw-r--r--video/out/vo.h352
-rw-r--r--video/out/vo_caca.c395
-rw-r--r--video/out/vo_corevideo.h28
-rw-r--r--video/out/vo_corevideo.m457
-rw-r--r--video/out/vo_direct3d.c2101
-rw-r--r--video/out/vo_image.c198
-rw-r--r--video/out/vo_lavc.c553
-rw-r--r--video/out/vo_null.c103
-rw-r--r--video/out/vo_opengl.c2419
-rw-r--r--video/out/vo_opengl_old.c1166
-rw-r--r--video/out/vo_opengl_shaders.glsl355
-rw-r--r--video/out/vo_vdpau.c1718
-rw-r--r--video/out/vo_x11.c620
-rw-r--r--video/out/vo_xv.c716
-rw-r--r--video/out/w32_common.c757
-rw-r--r--video/out/w32_common.h66
-rw-r--r--video/out/x11_common.c2404
-rw-r--r--video/out/x11_common.h184
41 files changed, 21338 insertions, 0 deletions
diff --git a/video/out/aspect.c b/video/out/aspect.c
new file mode 100644
index 0000000000..f3cd00a5e5
--- /dev/null
+++ b/video/out/aspect.c
@@ -0,0 +1,148 @@
+/*
+ * 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.
+ */
+
+/* Stuff for correct aspect scaling. */
+#include "aspect.h"
+#include "geometry.h"
+#include "video_out.h"
+#include "mp_msg.h"
+#include "options.h"
+
+#include "video_out.h"
+
+void aspect_save_videores(struct vo *vo, int w, int h, int d_w, int d_h)
+{
+ vo->aspdat.orgw = w;
+ vo->aspdat.orgh = h;
+ vo->aspdat.prew = d_w;
+ vo->aspdat.preh = d_h;
+ vo->aspdat.par = (double)d_w / d_h * h / w;
+}
+
+void aspect_save_screenres(struct vo *vo, int scrw, int scrh)
+{
+ mp_msg(MSGT_VO, MSGL_DBG2, "aspect_save_screenres %dx%d\n", scrw, scrh);
+ struct MPOpts *opts = vo->opts;
+ if (scrw <= 0 && scrh <= 0)
+ scrw = 1024;
+ if (scrh <= 0)
+ scrh = (scrw * 3 + 3) / 4;
+ if (scrw <= 0)
+ scrw = (scrh * 4 + 2) / 3;
+ vo->aspdat.scrw = scrw;
+ vo->aspdat.scrh = scrh;
+ if (opts->force_monitor_aspect)
+ vo->monitor_par = opts->force_monitor_aspect * scrh / scrw;
+ else
+ vo->monitor_par = 1.0 / opts->monitor_pixel_aspect;
+}
+
+/* aspect is called with the source resolution and the
+ * resolution, that the scaled image should fit into
+ */
+
+void aspect_fit(struct vo *vo, int *srcw, int *srch, int fitw, int fith)
+{
+ struct aspect_data *aspdat = &vo->aspdat;
+ float pixelaspect = vo->monitor_par;
+
+ mp_msg(MSGT_VO, MSGL_DBG2, "aspect(0) fitin: %dx%d monitor_par: %.2f\n",
+ fitw, fith, vo->monitor_par);
+ *srcw = fitw;
+ *srch = (float)fitw / aspdat->prew * aspdat->preh / pixelaspect;
+ *srch += *srch % 2; // round
+ mp_msg(MSGT_VO, MSGL_DBG2, "aspect(1) wh: %dx%d (org: %dx%d)\n",
+ *srcw, *srch, aspdat->prew, aspdat->preh);
+ if (*srch > fith || *srch < aspdat->orgh) {
+ int tmpw = (float)fith / aspdat->preh * aspdat->prew * pixelaspect;
+ tmpw += tmpw % 2; // round
+ if (tmpw <= fitw) {
+ *srch = fith;
+ *srcw = tmpw;
+ } else if (*srch > fith) {
+ mp_tmsg(MSGT_VO, MSGL_WARN,
+ "[ASPECT] Warning: No suitable new res found!\n");
+ }
+ }
+ aspdat->asp = *srcw / (float)*srch;
+ mp_msg(MSGT_VO, MSGL_DBG2, "aspect(2) wh: %dx%d (org: %dx%d)\n",
+ *srcw, *srch, aspdat->prew, aspdat->preh);
+}
+
+static void get_max_dims(struct vo *vo, int *w, int *h, int zoom)
+{
+ struct aspect_data *aspdat = &vo->aspdat;
+ *w = zoom ? aspdat->scrw : aspdat->prew;
+ *h = zoom ? aspdat->scrh : aspdat->preh;
+ if (zoom && WinID >= 0)
+ zoom = A_WINZOOM;
+ if (zoom == A_WINZOOM) {
+ *w = vo->dwidth;
+ *h = vo->dheight;
+ }
+}
+
+void aspect(struct vo *vo, int *srcw, int *srch, int zoom)
+{
+ int fitw;
+ int fith;
+ get_max_dims(vo, &fitw, &fith, zoom);
+ if (!zoom && geometry_wh_changed) {
+ mp_msg(MSGT_VO, MSGL_DBG2, "aspect(0) no aspect forced!\n");
+ return; // the user doesn't want to fix aspect
+ }
+ aspect_fit(vo, srcw, srch, fitw, fith);
+}
+
+void panscan_init(struct vo *vo)
+{
+ vo->panscan_x = 0;
+ vo->panscan_y = 0;
+ vo->panscan_amount = 0.0f;
+}
+
+static void panscan_calc_internal(struct vo *vo, int zoom)
+{
+ int fwidth, fheight;
+ int vo_panscan_area;
+ int max_w, max_h;
+ get_max_dims(vo, &max_w, &max_h, zoom);
+ struct MPOpts *opts = vo->opts;
+
+ if (opts->vo_panscanrange > 0) {
+ aspect(vo, &fwidth, &fheight, zoom);
+ vo_panscan_area = max_h - fheight;
+ if (!vo_panscan_area)
+ vo_panscan_area = max_w - fwidth;
+ vo_panscan_area *= opts->vo_panscanrange;
+ } else
+ vo_panscan_area = -opts->vo_panscanrange * max_h;
+
+ vo->panscan_amount = vo_fs || zoom == A_WINZOOM ? vo_panscan : 0;
+ vo->panscan_x = vo_panscan_area * vo->panscan_amount * vo->aspdat.asp;
+ vo->panscan_y = vo_panscan_area * vo->panscan_amount;
+}
+
+/**
+ * vos that set vo_dwidth and v_dheight correctly should call this to update
+ * vo_panscan_x and vo_panscan_y
+ */
+void panscan_calc_windowed(struct vo *vo)
+{
+ panscan_calc_internal(vo, A_WINZOOM);
+}
diff --git a/video/out/aspect.h b/video/out/aspect.h
new file mode 100644
index 0000000000..c5247421d2
--- /dev/null
+++ b/video/out/aspect.h
@@ -0,0 +1,37 @@
+/*
+ * 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_ASPECT_H
+#define MPLAYER_ASPECT_H
+/* Stuff for correct aspect scaling. */
+
+struct vo;
+void panscan_init(struct vo *vo);
+void panscan_calc_windowed(struct vo *vo);
+
+void aspect_save_videores(struct vo *vo, int w, int h, int d_w, int d_h);
+void aspect_save_screenres(struct vo *vo, int scrw, int scrh);
+
+#define A_WINZOOM 2 ///< zoom to fill window size
+#define A_ZOOM 1
+#define A_NOZOOM 0
+
+void aspect(struct vo *vo, int *srcw, int *srch, int zoom);
+void aspect_fit(struct vo *vo, int *srcw, int *srch, int fitw, int fith);
+
+#endif /* MPLAYER_ASPECT_H */
diff --git a/video/out/bitmap_packer.c b/video/out/bitmap_packer.c
new file mode 100644
index 0000000000..603a6ce410
--- /dev/null
+++ b/video/out/bitmap_packer.c
@@ -0,0 +1,227 @@
+/*
+ * Calculate how to pack bitmap rectangles into a larger surface
+ *
+ * Copyright 2009, 2012 Uoti Urpala
+ *
+ * This file is part of mplayer2.
+ *
+ * mplayer2 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.
+ *
+ * mplayer2 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 mplayer2. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+#include <assert.h>
+
+#include <libavutil/common.h>
+
+#include "talloc.h"
+#include "bitmap_packer.h"
+#include "mp_msg.h"
+#include "mpcommon.h"
+#include "sub/dec_sub.h"
+#include "fastmemcpy.h"
+
+#define IS_POWER_OF_2(x) (((x) > 0) && !(((x) - 1) & (x)))
+
+void packer_reset(struct bitmap_packer *packer)
+{
+ struct bitmap_packer old = *packer;
+ *packer = (struct bitmap_packer) {
+ .w_max = old.w_max,
+ .h_max = old.h_max,
+ };
+ talloc_free_children(packer);
+}
+
+void packer_get_bb(struct bitmap_packer *packer, struct pos out_bb[2])
+{
+ out_bb[0] = (struct pos) {0};
+ out_bb[1] = (struct pos) {
+ FFMIN(packer->used_width + packer->padding, packer->w),
+ FFMIN(packer->used_height + packer->padding, packer->h),
+ };
+}
+
+#define HEIGHT_SORT_BITS 4
+static int size_index(int s)
+{
+ int n = av_log2_16bit(s);
+ return (n << HEIGHT_SORT_BITS)
+ + (- 1 - (s << HEIGHT_SORT_BITS >> n) & (1 << HEIGHT_SORT_BITS) - 1);
+}
+
+/* Pack the given rectangles into an area of size w * h.
+ * The size of each rectangle is read from in[i].x / in[i].y.
+ * The height of each rectangle must be less than 65536.
+ * 'scratch' must point to work memory for num_rects+16 ints.
+ * The packed position for rectangle number i is set in out[i].
+ * Return 0 on success, -1 if the rectangles did not fit in w*h.
+ *
+ * The rectangles are placed in rows in order approximately sorted by
+ * height (the approximate sorting is simpler than a full one would be,
+ * and allows the algorithm to work in linear time). Additionally, to
+ * reduce wasted space when there are a few tall rectangles, empty
+ * lower-right parts of rows are filled recursively when the size of
+ * rectangles in the row drops past a power-of-two threshold. So if a
+ * row starts with rectangles of size 3x50, 10x40 and 5x20 then the
+ * free rectangle with corners (13, 20)-(w, 50) is filled recursively.
+ */
+static int pack_rectangles(struct pos *in, struct pos *out, int num_rects,
+ int w, int h, int *scratch, int *used_width)
+{
+ int bins[16 << HEIGHT_SORT_BITS];
+ int sizes[16 << HEIGHT_SORT_BITS] = { 0 };
+ for (int i = 0; i < num_rects; i++)
+ sizes[size_index(in[i].y)]++;
+ int idx = 0;
+ for (int i = 0; i < 16 << HEIGHT_SORT_BITS; i += 1 << HEIGHT_SORT_BITS) {
+ for (int j = 0; j < 1 << HEIGHT_SORT_BITS; j++) {
+ bins[i + j] = idx;
+ idx += sizes[i + j];
+ }
+ scratch[idx++] = -1;
+ }
+ for (int i = 0; i < num_rects; i++)
+ scratch[bins[size_index(in[i].y)]++] = i;
+ for (int i = 0; i < 16; i++)
+ bins[i] = bins[i << HEIGHT_SORT_BITS] - sizes[i << HEIGHT_SORT_BITS];
+ struct {
+ int size, x, bottom;
+ } stack[16] = {{15, 0, h}}, s = {};
+ int stackpos = 1;
+ int y;
+ while (stackpos) {
+ y = s.bottom;
+ s = stack[--stackpos];
+ s.size++;
+ while (s.size--) {
+ int maxy = -1;
+ int obj;
+ while ((obj = scratch[bins[s.size]]) >= 0) {
+ int bottom = y + in[obj].y;
+ if (bottom > s.bottom)
+ break;
+ int right = s.x + in[obj].x;
+ if (right > w)
+ break;
+ bins[s.size]++;
+ out[obj] = (struct pos){s.x, y};
+ num_rects--;
+ if (maxy < 0)
+ stack[stackpos++] = s;
+ s.x = right;
+ maxy = FFMAX(maxy, bottom);
+ }
+ *used_width = FFMAX(*used_width, s.x);
+ if (maxy > 0)
+ s.bottom = maxy;
+ }
+ }
+ return num_rects ? -1 : y;
+}
+
+int packer_pack(struct bitmap_packer *packer)
+{
+ if (packer->count == 0)
+ return 0;
+ int w_orig = packer->w, h_orig = packer->h;
+ struct pos *in = packer->in;
+ int xmax = 0, ymax = 0;
+ for (int i = 0; i < packer->count; i++) {
+ if (in[i].x <= packer->padding || in[i].y <= packer->padding)
+ in[i] = (struct pos){0, 0};
+ if (in[i].x < 0 || in [i].x > 65535 || in[i].y < 0 || in[i].y > 65535) {
+ mp_msg(MSGT_VO, MSGL_FATAL, "Invalid OSD / subtitle bitmap size\n");
+ abort();
+ }
+ xmax = FFMAX(xmax, in[i].x);
+ ymax = FFMAX(ymax, in[i].y);
+ }
+ xmax = FFMAX(0, xmax - packer->padding);
+ ymax = FFMAX(0, ymax - packer->padding);
+ if (xmax > packer->w)
+ packer->w = 1 << av_log2(xmax - 1) + 1;
+ if (ymax > packer->h)
+ packer->h = 1 << av_log2(ymax - 1) + 1;
+ while (1) {
+ int used_width = 0;
+ int y = pack_rectangles(in, packer->result, packer->count,
+ packer->w + packer->padding,
+ packer->h + packer->padding,
+ packer->scratch, &used_width);
+ if (y >= 0) {
+ // No padding at edges
+ packer->used_width = FFMIN(used_width, packer->w);
+ packer->used_height = FFMIN(y, packer->h);
+ assert(packer->w == 0 || IS_POWER_OF_2(packer->w));
+ assert(packer->h == 0 || IS_POWER_OF_2(packer->h));
+ return packer->w != w_orig || packer->h != h_orig;
+ }
+ if (packer->w <= packer->h && packer->w != packer->w_max)
+ packer->w = FFMIN(packer->w * 2, packer->w_max);
+ else if (packer->h != packer->h_max)
+ packer->h = FFMIN(packer->h * 2, packer->h_max);
+ else {
+ packer->w = w_orig;
+ packer->h = h_orig;
+ return -1;
+ }
+ }
+}
+
+void packer_set_size(struct bitmap_packer *packer, int size)
+{
+ packer->count = size;
+ if (size <= packer->asize)
+ return;
+ packer->asize = FFMAX(packer->asize * 2, size);
+ talloc_free(packer->result);
+ talloc_free(packer->scratch);
+ packer->in = talloc_realloc(packer, packer->in, struct pos, packer->asize);
+ packer->result = talloc_array_ptrtype(packer, packer->result,
+ packer->asize);
+ packer->scratch = talloc_array_ptrtype(packer, packer->scratch,
+ packer->asize + 16);
+}
+
+int packer_pack_from_subbitmaps(struct bitmap_packer *packer,
+ struct sub_bitmaps *b)
+{
+ packer->count = 0;
+ if (b->format == SUBBITMAP_EMPTY)
+ return 0;
+ packer_set_size(packer, b->num_parts);
+ int a = packer->padding;
+ for (int i = 0; i < b->num_parts; i++)
+ packer->in[i] = (struct pos){b->parts[i].w + a, b->parts[i].h + a};
+ return packer_pack(packer);
+}
+
+void packer_copy_subbitmaps(struct bitmap_packer *packer, struct sub_bitmaps *b,
+ void *data, int pixel_stride, int stride)
+{
+ assert(packer->count == b->num_parts);
+ if (packer->padding) {
+ struct pos bb[2];
+ packer_get_bb(packer, bb);
+ memset_pic(data, 0, bb[1].x * pixel_stride, bb[1].y, stride);
+ }
+ for (int n = 0; n < packer->count; n++) {
+ struct sub_bitmap *s = &b->parts[n];
+ struct pos p = packer->result[n];
+
+ void *pdata = (uint8_t *)data + p.y * stride + p.x * pixel_stride;
+ memcpy_pic(pdata, s->bitmap, s->w * pixel_stride, s->h,
+ stride, s->stride);
+ }
+}
diff --git a/video/out/bitmap_packer.h b/video/out/bitmap_packer.h
new file mode 100644
index 0000000000..b86c3ec4f9
--- /dev/null
+++ b/video/out/bitmap_packer.h
@@ -0,0 +1,68 @@
+#ifndef MPLAYER_PACK_RECTANGLES_H
+#define MPLAYER_PACK_RECTANGLES_H
+
+struct pos {
+ int x;
+ int y;
+};
+
+struct bitmap_packer {
+ int w;
+ int h;
+ int w_max;
+ int h_max;
+ int padding;
+ int count;
+ struct pos *in;
+ struct pos *result;
+ int used_width;
+ int used_height;
+
+ // internal
+ int *scratch;
+ int asize;
+};
+
+struct ass_image;
+struct sub_bitmaps;
+
+// Clear all internal state. Leave the following fields: w_max, h_max
+void packer_reset(struct bitmap_packer *packer);
+
+// Get the bounding box used for bitmap data (including padding).
+// The bounding box doesn't exceed (0,0)-(packer->w,packer->h).
+void packer_get_bb(struct bitmap_packer *packer, struct pos out_bb[2]);
+
+/* Reallocate packer->in for at least to desired number of items.
+ * Also sets packer->count to the same value.
+ */
+void packer_set_size(struct bitmap_packer *packer, int size);
+
+/* To use this, set packer->count to number of rectangles, w_max and h_max
+ * to maximum output rectangle size, and w and h to start size (may be 0).
+ * Write input sizes in packer->in.
+ * Resulting packing will be written in packer->result.
+ * w and h will be increased if necessary for successful packing.
+ * There is a strong guarantee that w and h will be powers of 2 (or set to 0).
+ * Return value is -1 if packing failed because w and h were set to max
+ * values but that wasn't enough, 1 if w or h was increased, and 0 otherwise.
+ */
+int packer_pack(struct bitmap_packer *packer);
+
+/* Like above, but packer->count will be automatically set and
+ * packer->in will be reallocated if needed and filled from the
+ * given image list.
+ */
+int packer_pack_from_subbitmaps(struct bitmap_packer *packer,
+ struct sub_bitmaps *b);
+
+// Copy the (already packed) sub-bitmaps from b to the image in data.
+// data must point to an image that is at least (packer->w, packer->h) big.
+// The image has the given stride (bytes between (x, y) to (x, y + 1)), and the
+// pixel format used by both the sub-bitmaps and the image uses pixel_stride
+// bytes per pixel (bytes between (x, y) to (x + 1, y)).
+// If packer->padding is set, the padding borders are cleared with 0.
+void packer_copy_subbitmaps(struct bitmap_packer *packer, struct sub_bitmaps *b,
+ void *data, int pixel_stride, int stride);
+
+#endif
diff --git a/video/out/cocoa_common.h b/video/out/cocoa_common.h
new file mode 100644
index 0000000000..079e497441
--- /dev/null
+++ b/video/out/cocoa_common.h
@@ -0,0 +1,55 @@
+/*
+ * Cocoa OpenGL Backend
+ *
+ * This file is part of mplayer2.
+ *
+ * mplayer2 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.
+ *
+ * mplayer2 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 mplayer2. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MPLAYER_COCOA_COMMON_H
+#define MPLAYER_COCOA_COMMON_H
+
+#include "video_out.h"
+
+struct vo_cocoa_state;
+
+bool vo_cocoa_gui_running(void);
+void *vo_cocoa_glgetaddr(const char *s);
+
+int vo_cocoa_init(struct vo *vo);
+void vo_cocoa_uninit(struct vo *vo);
+
+void vo_cocoa_update_xinerama_info(struct vo *vo);
+
+int vo_cocoa_change_attributes(struct vo *vo);
+int vo_cocoa_create_window(struct vo *vo, uint32_t d_width,
+ uint32_t d_height, uint32_t flags,
+ int gl3profile);
+
+void vo_cocoa_swap_buffers(struct vo *vo);
+int vo_cocoa_check_events(struct vo *vo);
+void vo_cocoa_fullscreen(struct vo *vo);
+void vo_cocoa_ontop(struct vo *vo);
+void vo_cocoa_pause(struct vo *vo);
+void vo_cocoa_resume(struct vo *vo);
+
+// returns an int to conform to the gl extensions from other platforms
+int vo_cocoa_swap_interval(int enabled);
+
+void *vo_cocoa_cgl_context(struct vo *vo);
+void *vo_cocoa_cgl_pixel_format(struct vo *vo);
+
+int vo_cocoa_cgl_color_size(struct vo *vo);
+
+#endif /* MPLAYER_COCOA_COMMON_H */
diff --git a/video/out/cocoa_common.m b/video/out/cocoa_common.m
new file mode 100644
index 0000000000..337e0a32be
--- /dev/null
+++ b/video/out/cocoa_common.m
@@ -0,0 +1,865 @@
+/*
+ * Cocoa OpenGL Backend
+ *
+ * This file is part of mplayer2.
+ *
+ * mplayer2 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.
+ *
+ * mplayer2 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 mplayer2. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#import <Cocoa/Cocoa.h>
+#import <CoreServices/CoreServices.h> // for CGDisplayHideCursor
+#import <IOKit/pwr_mgt/IOPMLib.h>
+#include <dlfcn.h>
+
+#include "cocoa_common.h"
+
+#include "config.h"
+
+#include "options.h"
+#include "video_out.h"
+#include "aspect.h"
+
+#include "mp_fifo.h"
+#include "talloc.h"
+
+#include "input/input.h"
+#include "input/keycodes.h"
+#include "osx_common.h"
+#include "mp_msg.h"
+
+#ifndef NSOpenGLPFAOpenGLProfile
+#define NSOpenGLPFAOpenGLProfile 99
+#endif
+
+#ifndef NSOpenGLProfileVersionLegacy
+#define NSOpenGLProfileVersionLegacy 0x1000
+#endif
+
+#ifndef NSOpenGLProfileVersion3_2Core
+#define NSOpenGLProfileVersion3_2Core 0x3200
+#endif
+
+#define NSLeftAlternateKeyMask (0x000020 | NSAlternateKeyMask)
+#define NSRightAlternateKeyMask (0x000040 | NSAlternateKeyMask)
+
+// add methods not available on OSX versions prior to 10.7
+#ifndef MAC_OS_X_VERSION_10_7
+@interface NSView (IntroducedInLion)
+- (NSRect)convertRectToBacking:(NSRect)aRect;
+- (void)setWantsBestResolutionOpenGLSurface:(BOOL)aBool;
+@end
+#endif
+
+// add power management assertion not available on OSX versions prior to 10.7
+#ifndef kIOPMAssertionTypePreventUserIdleDisplaySleep
+#define kIOPMAssertionTypePreventUserIdleDisplaySleep \
+ CFSTR("PreventUserIdleDisplaySleep")
+#endif
+
+@interface GLMPlayerWindow : NSWindow <NSWindowDelegate> {
+ struct vo *_vo;
+}
+- (void)setVideoOutput:(struct vo *)vo;
+- (BOOL)canBecomeKeyWindow;
+- (BOOL)canBecomeMainWindow;
+- (void)fullscreen;
+- (void)mouseEvent:(NSEvent *)theEvent;
+- (void)mulSize:(float)multiplier;
+- (void)setContentSize:(NSSize)newSize keepCentered:(BOOL)keepCentered;
+@end
+
+@interface GLMPlayerOpenGLView : NSView
+@end
+
+struct vo_cocoa_state {
+ NSAutoreleasePool *pool;
+ GLMPlayerWindow *window;
+ NSOpenGLContext *glContext;
+ NSOpenGLPixelFormat *pixelFormat;
+
+ NSSize current_video_size;
+ NSSize previous_video_size;
+
+ NSRect screen_frame;
+ NSScreen *screen_handle;
+ NSArray *screen_array;
+
+ NSInteger windowed_mask;
+ NSInteger fullscreen_mask;
+
+ NSRect windowed_frame;
+
+ NSString *window_title;
+
+ NSInteger window_level;
+ NSInteger fullscreen_window_level;
+
+ int display_cursor;
+ int cursor_timer;
+ int cursor_autohide_delay;
+
+ bool did_resize;
+ bool out_fs_resize;
+
+ IOPMAssertionID power_mgmt_assertion;
+};
+
+static int _instances = 0;
+
+static void create_menu(void);
+
+static struct vo_cocoa_state *vo_cocoa_init_state(struct vo *vo)
+{
+ struct vo_cocoa_state *s = talloc_ptrtype(vo, s);
+ *s = (struct vo_cocoa_state){
+ .pool = [[NSAutoreleasePool alloc] init],
+ .did_resize = NO,
+ .current_video_size = {0,0},
+ .previous_video_size = {0,0},
+ .windowed_mask = NSTitledWindowMask|NSClosableWindowMask|
+ NSMiniaturizableWindowMask|NSResizableWindowMask,
+ .fullscreen_mask = NSBorderlessWindowMask,
+ .windowed_frame = {{0,0},{0,0}},
+ .out_fs_resize = NO,
+ .display_cursor = 1,
+ .cursor_autohide_delay = vo->opts->cursor_autohide_delay,
+ .power_mgmt_assertion = kIOPMNullAss