cosmetics: stream_cdda.c: reformat
[mplayer.git] / libvo / vo_sharedbuffer.m
blob0b811f18484ac8832fe4282634b708043835b6ab
1 /*
2  * OSX Shared Buffer Video Output (extracted from mplayer's corevideo)
3  *
4  * This file is part of mplayer2.
5  *
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.
10  *
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.
15  *
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/>.
18  */
21  * This video output was extracted from mplayer's corevideo. It's purpose it
22  * to copy mp_image data to a shared buffer using mmap and to do simple
23  * coordination with the GUIs using Distributed Objects.
24  */
26 #include <sys/mman.h>
28 #include "vo_sharedbuffer.h"
29 #include "video_out.h"
30 #include "subopt-helper.h"
31 #include "talloc.h"
33 #include "libmpcodecs/vfcap.h"
34 #include "libmpcodecs/mp_image.h"
35 #include "fastmemcpy.h"
37 #include "sub/sub.h"
38 #include "osd.h"
40 // declarations
41 struct priv {
42     char *buffer_name;
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,
50         int dststride);
52     NSDistantObject *mposx_proxy;
53     id <MPlayerOSXVOProto> mposx_proto;
56 struct priv *p;
58 // implementation
59 static void draw_alpha(void *ctx, int x0, int y0, int w, int h,
60                             unsigned char *src, unsigned char *srca,
61                             int stride)
63     p->vo_draw_alpha_fnc(w, h, src, srca, stride,
64         p->image_data + (x0 + y0 * p->image_width) * p->image_bytespp,
65         p->image_width * p->image_bytespp);
68 static unsigned int image_bytes()
70     return p->image_width * p->image_height * p->image_bytespp;
73 static int preinit(struct vo *vo, const char *arg)
75     p = talloc_zero(NULL, struct priv);
77     const opt_t subopts[] = {
78         {"buffer_name", OPT_ARG_MSTRZ, &p->buffer_name, NULL},
79         {NULL}
80     };
82     if (subopt_parse(arg, subopts) != 0) {
83         mp_msg(MSGT_VO, MSGL_FATAL,
84             "\n-vo sharedbuffer command line help:\n"
85             "Example: mplayer -vo shared_buffer:buffer_name=mybuff\n"
86             "\nOptions:\n"
87             "  buffer_name=<name>\n"
88             "    Name of the shared buffer created with shm_open() as well as\n"
89             "    the name of the NSConnection mplayer2 will try to open.\n"
90             "Example: mplayer -vo sharedbuffer\n"
91             "\n" );
92         return -1;
93     }
95     if (!p->buffer_name) p->buffer_name = "mplayerosx";
97     return 0;
100 static void flip_page(struct vo *vo)
102     NSAutoreleasePool *pool = [NSAutoreleasePool new];
103     [p->mposx_proto render];
104     [pool release];
107 static void check_events(struct vo *vo) { }
109 static uint32_t draw_image(struct vo *vo, mp_image_t *mpi)
111     memcpy_pic(p->image_data, mpi->planes[0],
112                (p->image_width) * (p->image_bytespp), p->image_height,
113                (p->image_width) * (p->image_bytespp), mpi->stride[0]);
114     return 0;
117 static void draw_osd(struct vo *vo, struct osd_state *osd) {
118     osd_draw_text(osd, p->image_width, p->image_height, draw_alpha, vo);
121 static void free_buffers(void)
123     [p->mposx_proto stop];
124     p->mposx_proto = nil;
125     [p->mposx_proxy release];
126     p->mposx_proxy = nil;
128     if (p->image_data) {
129         if (munmap(p->image_data, image_bytes()) == -1)
130             mp_msg(MSGT_VO, MSGL_FATAL, "[vo_sharedbuffer] uninit: munmap "
131                                         "failed. Error: %s\n", strerror(errno));
133         if (shm_unlink(p->buffer_name) == -1)
134             mp_msg(MSGT_VO, MSGL_FATAL, "[vo_sharedbuffer] uninit: shm_unlink "
135                                         "failed. Error: %s\n", strerror(errno));
136     }
139 static int config(struct vo *vo, uint32_t width, uint32_t height,
140                   uint32_t d_width, uint32_t d_height, uint32_t flags,
141                   uint32_t format)
143     NSAutoreleasePool *pool = [NSAutoreleasePool new];
144     free_buffers();
146     p->image_width = width;
147     p->image_height = height;
149     mp_msg(MSGT_VO, MSGL_INFO, "[vo_sharedbuffer] writing output to a shared "
150         "buffer named \"%s\"\n", p->buffer_name);
152     // create shared memory
153     int shm_fd = shm_open(p->buffer_name, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
154     if (shm_fd == -1) {
155         mp_msg(MSGT_VO, MSGL_FATAL,
156             "[vo_sharedbuffer] failed to open shared memory. Error: %s\n",
157             strerror(errno));
158         goto err_out;
159     }
161     if (ftruncate(shm_fd, image_bytes()) == -1) {
162         mp_msg(MSGT_VO, MSGL_FATAL,
163             "[vo_sharedbuffer] failed to size shared memory, possibly "
164             "already in use. Error: %s\n", strerror(errno));
165         close(shm_fd);
166         shm_unlink(p->buffer_name);
167         goto err_out;
168     }
170     p->image_data = mmap(NULL, image_bytes(),
171         PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
172     close(shm_fd);
174     if (p->image_data == MAP_FAILED) {
175         mp_msg(MSGT_VO, MSGL_FATAL,
176             "[vo_sharedbuffer] failed to map shared memory. "
177             "Error: %s\n", strerror(errno));
178         shm_unlink(p->buffer_name);
179         goto err_out;
180     }
182     //connect to mplayerosx
183     p->mposx_proxy = [NSConnection
184         rootProxyForConnectionWithRegisteredName:
185                   [NSString stringWithUTF8String:p->buffer_name] host:nil];
187     if ([p->mposx_proxy conformsToProtocol:@protocol(MPlayerOSXVOProto)]) {
188         [p->mposx_proxy setProtocolForProxy:@protocol(MPlayerOSXVOProto)];
189         p->mposx_proto = (id <MPlayerOSXVOProto>)p->mposx_proxy;
190         [p->mposx_proto startWithWidth:p->image_width
191                             withHeight:p->image_height
192                              withBytes:p->image_bytespp
193                             withAspect:d_width*100/d_height];
194     } else {
195         mp_msg(MSGT_VO, MSGL_ERR,
196             "[vo_sharedbuffer] distributed object doesn't conform "
197             "to the correct protocol.\n");
198         [p->mposx_proxy release];
199         p->mposx_proxy = nil;
200         p->mposx_proto = nil;
201     }
203     [pool release];
204     return 0;
205 err_out:
206     [pool release];
207     return 1;
210 static int query_format(uint32_t format)
212   unsigned int image_depth = 0;
213   switch (format) {
214       case IMGFMT_YUY2:
215           p->vo_draw_alpha_fnc = vo_draw_alpha_yuy2;
216           image_depth = 16;
217           goto supported;
218       case IMGFMT_RGB24:
219           p->vo_draw_alpha_fnc = vo_draw_alpha_rgb24;
220           image_depth = 24;
221           goto supported;
222       case IMGFMT_ARGB:
223           p->vo_draw_alpha_fnc = vo_draw_alpha_rgb32;
224           image_depth = 32;
225           goto supported;
226       case IMGFMT_BGRA:
227           p->vo_draw_alpha_fnc = vo_draw_alpha_rgb32;
228           image_depth = 32;
229           goto supported;
230   }
231   return 0;
233 supported:
234     p->image_bytespp = (image_depth + 7) / 8;
235     return VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW |
236         VFCAP_OSD | VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN |
237         VOCAP_NOSLICES;
240 static void uninit(struct vo *vo)
242     free_buffers();
245 static int control(struct vo *vo, uint32_t request, void *data)
247     switch (request) {
248         case VOCTRL_DRAW_IMAGE:
249             return draw_image(vo, data);
250         case VOCTRL_FULLSCREEN:
251             [p->mposx_proto toggleFullscreen];
252             return VO_TRUE;
253         case VOCTRL_QUERY_FORMAT:
254             return query_format(*(uint32_t*)data);
255         case VOCTRL_ONTOP:
256             [p->mposx_proto ontop];
257             return VO_TRUE;
258     }
259     return VO_NOTIMPL;
262 const struct vo_driver video_out_sharedbuffer = {
263     .is_new = true,
264     .info = &(const vo_info_t) {
265         "Mac OS X Shared Buffer (headless video output for GUIs)",
266         "sharedbuffer",
267         "Stefano Pigozzi <stefano.pigozzi@gmail.com> and others.",
268         ""
269     },
270     .preinit = preinit,
271     .config = config,
272     .control = control,
273     .flip_page = flip_page,
274     .check_events = check_events,
275     .uninit = uninit,
276     .draw_osd = draw_osd