2 * OSX Shared Buffer Video Output (extracted from mplayer's corevideo)
4 * This file is part of mplayer2.
6 * mplayer2 is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * mplayer2 is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with mplayer2. If not, see <http://www.gnu.org/licenses/>.
21 * This video output was extracted from mplayer's corevideo. Its purpose is
22 * to copy mp_image data to a shared buffer using mmap and to do simple
23 * coordination with the GUIs using Distributed Objects.
28 #include "vo_sharedbuffer.h"
29 #include "video_out.h"
33 #include "libmpcodecs/vfcap.h"
34 #include "libmpcodecs/mp_image.h"
35 #include "fastmemcpy.h"
43 unsigned char *image_data;
44 unsigned int image_bytespp;
45 unsigned int image_width;
46 unsigned int image_height;
48 void (*vo_draw_alpha_fnc)(int w, int h, unsigned char* src,
49 unsigned char *srca, int srcstride, unsigned char* dstbase,
52 NSDistantObject *mposx_proxy;
53 id <MPlayerOSXVOProto> mposx_proto;
57 static void draw_alpha(void *ctx, int x0, int y0, int w, int h,
58 unsigned char *src, unsigned char *srca,
61 struct priv *p = ((struct vo *) ctx)->priv;
62 p->vo_draw_alpha_fnc(w, h, src, srca, stride,
63 p->image_data + (x0 + y0 * p->image_width) * p->image_bytespp,
64 p->image_width * p->image_bytespp);
67 static unsigned int image_bytes(struct priv *p)
69 return p->image_width * p->image_height * p->image_bytespp;
72 static int preinit(struct vo *vo, const char *arg)
77 static void flip_page(struct vo *vo)
79 struct priv *p = vo->priv;
80 NSAutoreleasePool *pool = [NSAutoreleasePool new];
81 [p->mposx_proto render];
85 static void check_events(struct vo *vo) { }
87 static uint32_t draw_image(struct vo *vo, mp_image_t *mpi)
89 struct priv *p = vo->priv;
90 memcpy_pic(p->image_data, mpi->planes[0],
91 (p->image_width) * (p->image_bytespp), p->image_height,
92 (p->image_width) * (p->image_bytespp), mpi->stride[0]);
96 static void draw_osd(struct vo *vo, struct osd_state *osd) {
97 struct priv *p = vo->priv;
98 osd_draw_text(osd, p->image_width, p->image_height, draw_alpha, vo);
101 static void free_buffers(struct priv *p)
103 [p->mposx_proto stop];
104 p->mposx_proto = nil;
105 [p->mposx_proxy release];
106 p->mposx_proxy = nil;
109 if (munmap(p->image_data, image_bytes(p)) == -1)
110 mp_msg(MSGT_VO, MSGL_FATAL, "[vo_sharedbuffer] uninit: munmap "
111 "failed. Error: %s\n", strerror(errno));
113 if (shm_unlink(p->buffer_name) == -1)
114 mp_msg(MSGT_VO, MSGL_FATAL, "[vo_sharedbuffer] uninit: shm_unlink "
115 "failed. Error: %s\n", strerror(errno));
119 static int config(struct vo *vo, uint32_t width, uint32_t height,
120 uint32_t d_width, uint32_t d_height, uint32_t flags,
123 struct priv *p = vo->priv;
124 NSAutoreleasePool *pool = [NSAutoreleasePool new];
127 p->image_width = width;
128 p->image_height = height;
130 mp_msg(MSGT_VO, MSGL_INFO, "[vo_sharedbuffer] writing output to a shared "
131 "buffer named \"%s\"\n", p->buffer_name);
133 // create shared memory
134 int shm_fd = shm_open(p->buffer_name, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
136 mp_msg(MSGT_VO, MSGL_FATAL,
137 "[vo_sharedbuffer] failed to open shared memory. Error: %s\n",
142 if (ftruncate(shm_fd, image_bytes(p)) == -1) {
143 mp_msg(MSGT_VO, MSGL_FATAL,
144 "[vo_sharedbuffer] failed to size shared memory, possibly "
145 "already in use. Error: %s\n", strerror(errno));
147 shm_unlink(p->buffer_name);
151 p->image_data = mmap(NULL, image_bytes(p),
152 PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
155 if (p->image_data == MAP_FAILED) {
156 mp_msg(MSGT_VO, MSGL_FATAL,
157 "[vo_sharedbuffer] failed to map shared memory. "
158 "Error: %s\n", strerror(errno));
159 shm_unlink(p->buffer_name);
163 //connect to mplayerosx
164 p->mposx_proxy = [NSConnection
165 rootProxyForConnectionWithRegisteredName:
166 [NSString stringWithUTF8String:p->buffer_name] host:nil];
168 if ([p->mposx_proxy conformsToProtocol:@protocol(MPlayerOSXVOProto)]) {
169 [p->mposx_proxy setProtocolForProxy:@protocol(MPlayerOSXVOProto)];
170 p->mposx_proto = (id <MPlayerOSXVOProto>)p->mposx_proxy;
171 [p->mposx_proto startWithWidth:p->image_width
172 withHeight:p->image_height
173 withBytes:p->image_bytespp
174 withAspect:d_width*100/d_height];
176 mp_msg(MSGT_VO, MSGL_ERR,
177 "[vo_sharedbuffer] distributed object doesn't conform "
178 "to the correct protocol.\n");
179 [p->mposx_proxy release];
180 p->mposx_proxy = nil;
181 p->mposx_proto = nil;
191 static int query_format(struct vo *vo, uint32_t format)
193 struct priv *p = vo->priv;
194 unsigned int image_depth = 0;
197 p->vo_draw_alpha_fnc = vo_draw_alpha_yuy2;
201 p->vo_draw_alpha_fnc = vo_draw_alpha_rgb24;
205 p->vo_draw_alpha_fnc = vo_draw_alpha_rgb32;
209 p->vo_draw_alpha_fnc = vo_draw_alpha_rgb32;
216 p->image_bytespp = (image_depth + 7) / 8;
217 return VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW |
218 VFCAP_OSD | VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN |
222 static void uninit(struct vo *vo)
224 struct priv *p = vo->priv;
228 static int control(struct vo *vo, uint32_t request, void *data)
230 struct priv *p = vo->priv;
232 case VOCTRL_DRAW_IMAGE:
233 return draw_image(vo, data);
234 case VOCTRL_FULLSCREEN:
235 [p->mposx_proto toggleFullscreen];
237 case VOCTRL_QUERY_FORMAT:
238 return query_format(vo, *(uint32_t*)data);
240 [p->mposx_proto ontop];
246 #undef OPT_BASE_STRUCT
247 #define OPT_BASE_STRUCT struct priv
249 const struct vo_driver video_out_sharedbuffer = {
251 .info = &(const vo_info_t) {
252 "Mac OS X Shared Buffer (headless video output for GUIs)",
254 "Stefano Pigozzi <stefano.pigozzi@gmail.com> and others.",
260 .flip_page = flip_page,
261 .check_events = check_events,
263 .draw_osd = draw_osd,
264 .privsize = sizeof(struct priv),
265 .options = (const struct m_option[]) {
266 OPT_STRING("buffer_name", buffer_name, 0, OPTDEF_STR("mplayerosx")),