diff options
Diffstat (limited to 'libvo/vo_zr.c')
-rw-r--r-- | libvo/vo_zr.c | 837 |
1 files changed, 0 insertions, 837 deletions
diff --git a/libvo/vo_zr.c b/libvo/vo_zr.c deleted file mode 100644 index 4cb1ed0de6..0000000000 --- a/libvo/vo_zr.c +++ /dev/null @@ -1,837 +0,0 @@ -/* - * playback on Zoran cards - * copyright (C) 2001, 2003 Rik Snel - * - * 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. - */ - -/* $Id$ */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <fcntl.h> -#include <errno.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <sys/time.h> -#include <sys/mman.h> -#include <sys/ioctl.h> -#include <linux/types.h> -#include <linux/videodev.h> -#include "config.h" -#include "videodev_mjpeg.h" -#include "video_out.h" -#include "video_out_internal.h" -#include "mp_msg.h" -#include "m_option.h" -#include "fastmemcpy.h" -#include "jpeg_enc.h" -#include "vo_zr.h" - -static const vo_info_t info = -{ - "Zoran ZR360[56]7/ZR36060 Driver (DC10(+)/buz/lml33/MatroxRR)", - "zr", - "Rik Snel <rsnel@cube.dyndns.org>", - "" -}; - -const LIBVO_EXTERN (zr) - -#define ZR_MAX_DEVICES 4 -/* General variables */ - -typedef struct { - int width; - int height; - int xoff; - int yoff; - int set; -} geo_t; - -static int zr_count = 1; -static int zr_parsing = 0; -static int framenum; - -typedef struct { - /* commandline args given for this device (and defaults) */ - int vdec, hdec; /* requested decimation 1,2,4 */ - int fd; /* force decimation */ - int xdoff, ydoff; /* offset from upperleft of screen - * default is 'centered' */ - int quality; /* jpeg quality 1=best, 20=bad */ - geo_t g; /* view window (zrcrop) */ - char *device; /* /dev/video1 */ - int bw; /* if bw == 1, display in black&white */ - int norm; /* PAL/NTSC */ - - /* buffers + pointers + info */ - - unsigned char *image; - int image_width, image_height, size; - int off_y, off_c, stride; /* for use by 'draw slice/frame' */ - - unsigned char *buf; /* the jpeg images will be placed here */ - jpeg_enc_t *j; - unsigned char *y_data, *u_data, *v_data; /* used by the jpeg encoder */ - int y_stride, u_stride, v_stride; /* these point somewhere in image */ - - /* information for (and about) the zoran card */ - - int vdes; /* file descriptor of card */ - int frame, synco, queue; /* buffer management */ - struct mjpeg_sync zs; /* state information */ - struct mjpeg_params p; - struct mjpeg_requestbuffers zrq; - struct video_capability vc; /* max resolution and so on */ - int fields, stretchy; /* must the *image be interlaced - or stretched to fit on the screen? */ -} zr_info_t; - -static zr_info_t zr_info[ZR_MAX_DEVICES] = { - {1, 1, 1, -1, -1, 2, {0, 0, 0, 0, 0}, NULL, 0, VIDEO_MODE_AUTO, NULL, 0, 0, 0, 0, 0, - 0, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {1, 1, 1, -1, -1, 2, {0, 0, 0, 0, 0}, NULL, 0, VIDEO_MODE_AUTO, NULL, 0, 0, 0, 0, 0, - 0, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {1, 1, 1, -1, -1, 2, {0, 0, 0, 0, 0}, NULL, 0, VIDEO_MODE_AUTO, NULL, 0, 0, 0, 0, 0, - 0, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {1, 1, 1, -1, -1, 2, {0, 0, 0, 0, 0}, NULL, 0, VIDEO_MODE_AUTO, NULL, 0, 0, 0, 0, 0, - 0, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}; - - - - -#define MJPEG_NBUFFERS 2 -#define MJPEG_SIZE 1024*256 - - -int zoran_getcap(zr_info_t *zr) { - char* dev = NULL; - - if (zr->device) - dev = zr->device; - else { - struct stat vstat; - const char *devs[] = { - "/dev/video", - "/dev/video0", - "/dev/v4l/video0", - "/dev/v4l0", - "/dev/v4l", - NULL - }; - int i = 0; - - do - { - if ((stat(devs[i], &vstat) == 0) && S_ISCHR(vstat.st_mode)) - { - dev = devs[i]; - mp_msg(MSGT_VO, MSGL_V, "zr: found video device %s\n", dev); - break; - } - } while (devs[++i] != NULL); - - if (!dev) - { - mp_msg(MSGT_VO, MSGL_ERR, "zr: unable to find video device\n"); - return 1; - } - } - - zr->vdes = open(dev, O_RDWR); - - if (zr->vdes < 0) { - mp_msg(MSGT_VO, MSGL_ERR, "zr: error opening %s: %s\n", - dev, strerror(errno)); - return 1; - } - - /* before we can ask for the maximum resolution, we must set - * the correct tv norm */ - - if (ioctl(zr->vdes, MJPIOC_G_PARAMS, &zr->p) < 0) { - mp_msg(MSGT_VO, MSGL_ERR, "zr: device at %s is probably not a DC10(+)/buz/lml33\n", dev); - return 1; - } - - if (zr->p.norm != zr->norm && zr->norm != VIDEO_MODE_AUTO) { - /* attempt to set requested norm */ - zr->p.norm = zr->norm; - if (ioctl(zr->vdes, MJPIOC_S_PARAMS, &zr->p) < 0) { - mp_msg(MSGT_VO, MSGL_ERR, - "zr: unable to change video norm, use another program to change it (XawTV)\n"); - return 1; - } - ioctl(zr->vdes, MJPIOC_G_PARAMS, &zr->p); - if (zr->norm != zr->p.norm) { - mp_msg(MSGT_VO, MSGL_ERR, - "zr: unable to change video norm, use another program to change it (XawTV)\n"); - return 1; - } - } - - if (ioctl(zr->vdes, VIDIOCGCAP, &zr->vc) < 0) { - mp_msg(MSGT_VO, MSGL_ERR, "zr: error getting video capabilities from %s\n", dev); - return 1; - } - mp_msg(MSGT_VO, MSGL_V, "zr: MJPEG card reports maxwidth=%d, maxheight=%d\n", zr->vc.maxwidth, zr->vc.maxheight); - - return 0; -} - -int init_zoran(zr_info_t *zr, int stretchx, int stretchy) { - /* center the image, and stretch it as far as possible (try to keep - * aspect) and check if it fits */ - if (zr->image_width > zr->vc.maxwidth) { - mp_msg(MSGT_VO, MSGL_ERR, "zr: movie to be played is too wide, max width currently %d\n", zr->vc.maxwidth); - return 1; - } - - if (zr->image_height > zr->vc.maxheight) { - mp_msg(MSGT_VO, MSGL_ERR, "zr: movie to be played is too high, max height currently %d\n", zr->vc.maxheight); - return 1; - } - - zr->p.decimation = 0; - zr->p.HorDcm = stretchx; - zr->p.VerDcm = stretchy; - zr->p.TmpDcm = 1; - zr->p.field_per_buff = zr->fields; - if (zr->xdoff == -1) { - zr->p.img_x = (zr->vc.maxwidth - - zr->p.HorDcm*(int)zr->image_width/zr->hdec)/2; - } else { - zr->p.img_x = zr->xdoff; - } - if (zr->ydoff == -1) { - zr->p.img_y = (zr->vc.maxheight - zr->p.VerDcm* - (3-zr->fields)*(int)zr->image_height)/4; - } else { - zr->p.img_y = zr->ydoff; - } - zr->p.img_width = zr->p.HorDcm*zr->image_width/zr->hdec; - zr->p.img_height = zr->p.VerDcm*zr->image_height/zr->fields; - mp_msg(MSGT_VO, MSGL_V, "zr: geometry (after 'scaling'): %dx%d+%d+%d fields=%d, w=%d, h=%d\n", zr->p.img_width, (3-zr->fields)*zr->p.img_height, zr->p.img_x, zr->p.img_y, zr->fields, zr->image_width/zr->hdec, zr->image_height); - - if (ioctl(zr->vdes, MJPIOC_S_PARAMS, &zr->p) < 0) { - mp_msg(MSGT_VO, MSGL_ERR, "zr: error setting display parameters\n"); - return 1; - } - - zr->zrq.count = MJPEG_NBUFFERS; - zr->zrq.size = MJPEG_SIZE; - - if (ioctl(zr->vdes, MJPIOC_REQBUFS, &zr->zrq)) { - mp_msg(MSGT_VO, MSGL_ERR, "zr: error requesting %ld buffers of size %ld\n", zr->zrq.count, zr->zrq.size); - return 1; - } - - /* the buffer count allocated may be different to the request */ - zr->buf = (unsigned char*)mmap(0, zr->zrq.count*zr->zrq.size, - PROT_READ|PROT_WRITE, MAP_SHARED, zr->vdes, 0); - - if (zr->buf == MAP_FAILED) { - mp_msg(MSGT_VO, MSGL_ERR, "zr: error requesting %ld buffers of size %ld\n", zr->zrq.count, zr->zrq.size); - return 1; - } - - mp_msg(MSGT_VO, MSGL_V, "zr: got %ld buffers of size %ld (wanted %d buffers of size %d)\n", zr->zrq.count, zr->zrq.size, MJPEG_NBUFFERS, MJPEG_SIZE); - if (zr->zrq.count < MJPEG_NBUFFERS) { - mp_msg(MSGT_VO, MSGL_V, "zr: got not enough buffers\n"); - return 1; - } - - zr->queue = 0; - zr->synco = 0; - - return 0; -} - -void uninit_zoran(zr_info_t *zr) { - free(zr->image); - zr->image=NULL; - while (zr->queue > zr->synco + 1) { - if (ioctl(zr->vdes, MJPIOC_SYNC, &zr->zs) < 0) - mp_msg(MSGT_VO, MSGL_ERR, "zr: error waiting for buffers to become free\n"); - zr->synco++; - } - /* stop streaming */ - zr->frame = -1; - if (ioctl(zr->vdes, MJPIOC_QBUF_PLAY, &zr->frame) < 0) - mp_msg(MSGT_VO, MSGL_ERR, "zr: error stopping playback of last frame\n"); - if (munmap(zr->buf,zr->zrq.count*zr->zrq.size)) - mp_msg(MSGT_VO, MSGL_ERR, "zr: error unmapping buffer\n"); - close(zr->vdes); -} - -int zr_geometry_sane(geo_t *g, unsigned int width, unsigned int height) { - if (g->set) { - if (g->width%2 != 0 || g->height%2 != 0 || - g->xoff%2 != 0 || g->yoff%2 != 0) { - mp_msg(MSGT_VO, MSGL_ERR, "zr: arguments in -zrcrop must be multiples of 2\n"); - return 1; - } - if (g->width <= 0 || g->height <= 0 || - g->xoff < 0 || g->yoff < 0) { - mp_msg(MSGT_VO, MSGL_ERR, "zr: width and height must be positive and offset nonnegative\n"); - return 1; - } - if (g->width + g->xoff > width) { - mp_msg(MSGT_VO, MSGL_ERR, "zr: width+xoffset (%d+%d>%d) is too big\n", g->width, g->xoff, width); - return 1; - } - if (g->height + g->yoff > height) { - mp_msg(MSGT_VO, MSGL_ERR, "zr: height+yoffset (%d+%d>%d) is too big\n", g->height, g->yoff, height); - return 1; - } - } else { - g->width = width; - g->height = height; - g->xoff = 0; - g->yoff = 0; - g->set = 1; - } - return 0; -} - - -static int config(uint32_t width, uint32_t height, uint32_t d_width, - uint32_t d_height, uint32_t flags, char *title, uint32_t format) -{ - int i, tmp, stretchx, stretchy; - framenum = 0; - if (format != IMGFMT_YV12 && format != IMGFMT_YUY2) { - printf("vo_zr called with wrong format"); - return 1; - } - for (i = 0; i < zr_count; i++) { - zr_info_t *zr = &zr_info[i]; - geo_t *g = &zr->g; - - zr->stride = 2*width; - if (zr_geometry_sane(g, width, height)) return 1; - - /* we must know the maximum resolution of the device - * it differs for DC10+ and buz for example */ - zoran_getcap(zr); /*must be called before init_zoran */ - /* make the scaling decision - * we are capable of stretching the image in the horizontal - * direction by factors 1, 2 and 4 - * we can stretch the image in the vertical direction by a - * factor of 1 and 2 AND we must decide about interlacing */ - if (g->width > zr->vc.maxwidth/2 || - g->height > zr->vc.maxheight/2) { - stretchx = 1; - stretchy = 1; - zr->fields = 2; - if (zr->vdec == 2) { - zr->fields = 1; - } else if (zr->vdec == 4) { - zr->fields = 1; - stretchy = 2; - } - stretchx = zr->hdec; - } else if (g->width > zr->vc.maxwidth/4 || - g->height > zr->vc.maxheight/4) { - stretchx = 2; - stretchy = 1; - zr->fields = 1; - if (zr->vdec == 2) { - stretchy = 2; - } else if (zr->vdec == 4) { - if (!zr->fd) { - mp_msg(MSGT_VO, MSGL_WARN, "zr: vertical decimation too high, changing to 2 (use -zrfd to keep vdec=4)\n"); - zr->vdec = 2; - } - stretchy = 2; - } - if (zr->hdec == 2) { - stretchx = 4; - } else if (zr->hdec == 4){ - if (!zr->fd) { - mp_msg(MSGT_VO, MSGL_WARN, "zr: horizontal decimation too high, changing to 2 (use -zrfd to keep hdec=4)\n"); - zr->hdec = 2; - } - stretchx = 4; - } - } else { - /* output image is maximally stretched */ - stretchx = 4; - stretchy = 2; - zr->fields = 1; - if (zr->vdec != 1 && !zr->fd) { - mp_msg(MSGT_VO, MSGL_WARN, "zr: vertical decimation too high, changing to 1 (use -zrfd to keep vdec=%d)\n", zr->vdec); - zr->vdec = 1; - } - if (zr->hdec != 1 && !zr->fd) { - mp_msg(MSGT_VO, MSGL_WARN, "zr: vertical decimation too high, changing to 1 (use -zrfd to keep hdec=%d)\n", zr->hdec); - zr->hdec = 1; - } - } - /* It can be that the original frame was too big for display, - * or that the width of the decimated image (for example) after - * padding up to a multiple of 16 has become too big. (orig - * width 720 (exactly right for the Buz) after decimation 360, - * after padding up to a multiple of 16 368, display 736 -> too - * large). In these situations we auto(re)crop. */ - tmp = 16*((g->width - 1)/(zr->hdec*16) + 1); - if (stretchx*tmp > zr->vc.maxwidth) { - g->xoff += 2*((g->width - zr->hdec*(tmp-16))/4); - /* g->off must be a multiple of 2 */ - g->width = zr->hdec*(tmp - 16); - g->set = 0; /* we abuse this field to - report that g has changed*/ - } - tmp = 8*zr->fields*((g->height - 1)/(zr->vdec*zr->fields*8)+1); - if (stretchy*tmp > zr->vc.maxheight) { - g->yoff += 2*((g->height - zr->vdec* - (tmp - 8*zr->fields))/4); - g->height = zr->vdec*(tmp - 8*zr->fields); - g->set = 0; - } - if (!g->set) - mp_msg(MSGT_VO, MSGL_V, "zr: auto(re)cropping %dx%d+%d+%d to make the image fit on the screen\n", g->width, g->height, g->xoff, g->yoff); - - /* the height must be a multiple of fields*8 and the width - * must be a multiple of 16 */ - /* add some black borders to make it so, and center the image*/ - zr->image_height = zr->fields*8*((g->height/zr->vdec - 1)/ - (zr->fields*8) + 1); - zr->image_width = (zr->hdec*16)*((g->width - 1)/(zr->hdec*16) + 1); - zr->off_y = (zr->image_height - g->height/zr->vdec)/2; - if (zr->off_y%2 != 0) zr->off_y++; - zr->off_y *= zr->image_width; - zr->off_c = zr->off_y/4; - zr->off_y += (zr->image_width - g->width)/2; - if (zr->off_y%2 != 0) zr->off_y--; - zr->off_c += (zr->image_width - g->width)/4; - zr->size = zr->image_width*zr->image_height; - mp_msg(MSGT_VO, MSGL_V, "zr: input: %dx%d, cropped: %dx%d, output: %dx%d, off_y=%d, off_c=%d\n", width, height, g->width, g->height, zr->image_width, zr->image_height, zr->off_y, zr->off_c); - - zr->image = malloc(2*zr->size); /* this buffer allows for YUV422 data, - * so it is a bit too big for YUV420 */ - if (!zr->image) { - mp_msg(MSGT_VO, MSGL_ERR, "zr: Memory exhausted\n"); - return 1; - } - /* and make sure that the borders are _really_ black */ - switch (format) { - case IMGFMT_YV12: - memset(zr->image, 0, zr->size); - memset(zr->image + zr->size, 0x80, zr->size/4); - memset(zr->image + 3*zr->size/2, 0x80, zr->size/4); - zr->y_data = zr->image; - zr->u_data = zr->image + zr->size; - zr->v_data = zr->image + 3*zr->size/2; - - zr->y_stride = zr->image_width; - zr->u_stride = zr->image_width/2; - zr->v_stride = zr->image_width/2; - - zr->j = jpeg_enc_init(zr->image_width/zr->hdec, - zr->image_height/zr->fields, - zr->hdec, zr->y_stride*zr->fields, - zr->hdec, zr->u_stride*zr->fields, - zr->hdec, zr->v_stride*zr->fields, - 1, zr->quality, zr->bw); - break; - case IMGFMT_YUY2: - for (tmp = 0; tmp < 2*zr->size; tmp+=4) { - zr->image[tmp] = 0; - zr->image[tmp+1] = 0x80; - zr->image[tmp+2] = 0; - zr->image[tmp+3] = 0x80; - } - - zr->y_data = zr->image; - zr->u_data = zr->image + 1; - zr->v_data = zr->image + 3; - - zr->y_stride = 2*zr->image_width; - zr->u_stride = 2*zr->image_width; - zr->v_stride = 2*zr->image_width; - - zr->j = jpeg_enc_init(zr->image_width/zr->hdec, - zr->image_height/zr->fields, - zr->hdec*2, - zr->y_stride*zr->fields, - zr->hdec*4, - zr->u_stride*zr->fields, - zr->hdec*4, - zr->v_stride*zr->fields, - 0, zr->quality, zr->bw); - break; - default: - mp_msg(MSGT_VO, MSGL_FATAL, "zr: internal inconsistency in vo_zr\n"); - } - - - if (zr->j == NULL) { - mp_msg(MSGT_VO, MSGL_ERR, "zr: error initializing the jpeg encoder\n"); - return 1; - } - - if (init_zoran(zr, stretchx, stretchy)) { - return 1; - } - - } - return 0; -} - -static void draw_osd(void) { -} - -static void flip_page (void) { - int i, j, k; - //FILE *fp; - //char filename[100]; - /* do we have a free buffer? */ - for (j = 0; j < zr_count; j++) { - zr_info_t *zr = &zr_info[j]; - /* using MJPEG_NBUFFERS here, using the real number of - * buffers may give sync issues (real number of buffers - * is always sufficient) */ - if (zr->queue-zr->synco < MJPEG_NBUFFERS) { - zr->frame = zr->queue; - } else { - if (ioctl(zr->vdes, MJPIOC_SYNC, &zr->zs) < 0) - mp_msg(MSGT_VO, MSGL_ERR, "zr: error waiting for buffers to become free\n"); - zr->frame = zr->zs.frame; - zr->synco++; - } - k=0; - for (i = 0; i < zr->fields; i++) - k+=jpeg_enc_frame(zr->j, zr->y_data + i*zr->y_stride, - zr->u_data + i*zr->u_stride, - zr->v_data + i*zr->v_stride, - zr->buf + zr->frame*zr->zrq.size+k); - if (k > zr->zrq.size) mp_msg(MSGT_VO, MSGL_WARN, "zr: jpeg image too large for maximum buffer size. Lower the jpeg encoding\nquality or the resolution of the movie.\n"); - } - /* Warning: Only the first jpeg image contains huffman- and - * quantisation tables, so don't expect files other than - * test0001.jpg to be readable */ - /*sprintf(filename, "test%04d.jpg", framenum); - fp = fopen(filename, "w"); - if (!fp) exit(1); - fwrite(buf+frame*zrq.size, 1, k, fp); - fclose(fp);*/ - /*fp = fopen("test1.jpg", "r"); - fread(buf+frame*zrq.size, 1, 2126, fp); - fclose(fp);*/ - - for (j = 0; j < zr_count; j++) { - zr_info_t *zr = &zr_info[j]; - if (ioctl(zr->vdes, MJPIOC_QBUF_PLAY, &zr->frame) < 0) - mp_msg(MSGT_VO, MSGL_ERR, "zr: error queueing buffer for playback\n"); - zr->queue++; - } - - framenum++; - return; -} - -static int draw_frame(uint8_t * src[]) { - int i, j; - char *source, *dest; - //printf("draw frame called\n"); - for (j = 0; j < zr_count; j++) { - zr_info_t *zr = &zr_info[j]; - geo_t *g = &zr->g; - source = src[0] + 2*g->yoff*zr->vdec*zr->stride + 2*g->xoff; - dest = zr->image + 2*zr->off_y; - for (i = 0; i < g->height/zr->vdec; i++) { - fast_memcpy(dest, source, zr->image_width*2); - dest += 2*zr->image_width; - source += zr->vdec*zr->stride; - } - } - return 0; -} - -static int query_format(uint32_t format) { - if(format==IMGFMT_YV12 || format==IMGFMT_YUY2) - return VFCAP_CSP_SUPPORTED|VFCAP_CSP_SUPPORTED_BY_HW; - return 0; -} - -static void uninit(void) { - int j; - mp_msg(MSGT_VO, MSGL_V, "zr: uninit called\n"); - for (j = 0; j < zr_count; j++) { - jpeg_enc_uninit(zr_info[j].j); - uninit_zoran(&zr_info[j]); - } -} - -static void check_events(void) { -} - - -static int draw_slice(uint8_t *srcimg[], int stride[], - int wf, int hf, int xf, int yf) { - int i, j, w, h, x, y; - /* Apply 'geometry', crop unwanted parts */ - uint8_t *dst; - //printf("before: w=%d, h=%d, x=%d, y=%d, src0=%p, src1=%p, src2=%p\n", w, h, x, y, srcimg[0], srcimg[1], srcimg[2]); - for (j = 0; j < zr_count; j++) { - uint8_t *src=srcimg[0]; - uint8_t *src1=srcimg[1]; - uint8_t *src2=srcimg[2]; - zr_info_t *zr = &zr_info[j]; - geo_t *g = &zr->g; - w = wf; h = hf; x = xf; y = yf; - if (x < g->xoff) { - src += g->xoff - x; - src1 += (g->xoff - x)/2; - src2 += (g->xoff - x)/2; - w -= g->xoff - x; - if (w < 0) break; //return 0; - x = 0 /*g.xoff*/; - } else { - x -= g->xoff; - } - if (x + w > g->width) { - w = g->width - x; - if (w < 0) break; //return 0; - } - if (y < g->yoff) { - src += (g->yoff - y)*stride[0]; - src1 += ((g->yoff - y)/2)*stride[1]; - src2 += ((g->yoff - y)/2)*stride[2]; - h -= g->yoff - y; - if (h < 0) break; //return 0; - y = 0; - } else { - y -= g->yoff; - } - if (y + h > g->height) { - h = g->height - y; - if (h < 0) break; //return 0; - } - //printf("after: w=%d, h=%d, x=%d, y=%d, src0=%p, src1=%p, src2=%p\n", w, h, x, y, srcimg[0], srcimg[1], srcimg[2]); - dst=zr->image + zr->off_y + zr->image_width*(y/zr->vdec)+x; - // copy Y: - for (i = 0; i < h; i++) { - if ((i + x)%zr->vdec == 0) { - fast_memcpy(dst,src,w); - dst+=zr->image_width; - } - src+=stride[0]; - - } - if (!zr->bw) { - // copy U+V: - uint8_t *dst1=zr->image + zr->size + zr->off_c+ (y/(zr->vdec*2))*zr->image_width/2+(x/2); - uint8_t *dst2=zr->image + 3*zr->size/2 + zr->off_c + - (y/(zr->vdec*2))* - zr->image_width/2+(x/2); - for (i = 0; i< h/2; i++) { - if ((i+x/2)%zr->vdec == 0) { - fast_memcpy(dst1,src1,w/2); - fast_memcpy(dst2,src2,w/2); - dst1+=zr->image_width/2; - dst2+=zr->image_width/2; - } - src1+=stride[1]; - src2+=stride[2]; - } - } - } - return 0; -} - - -/* copied and adapted from vo_aa_parseoption */ -int -vo_zr_parseoption(const m_option_t* conf, const char *opt, const char *param){ - /* got an option starting with zr */ - zr_info_t *zr = &zr_info[zr_parsing]; - int i; - /* do WE need it ?, always */ - if (!strcasecmp(opt, "zrdev")) { - if (param == NULL) return ERR_MISSING_PARAM; - //if ((i=getcolor(param))==-1) return ERR_OUT_OF_RANGE; - //aaopt_osdcolor=i; - free(zr->device); - zr->device = malloc(strlen(param)+1); - strcpy(zr->device, param); - mp_msg(MSGT_VO, MSGL_V, "zr: using device %s\n", zr->device); - return 1; - } else if (!strcasecmp(opt, "zrbw")) { - if (param != NULL) { - return ERR_OUT_OF_RANGE; - } - zr->bw = 1; - return 1; - } else if (!strcasecmp(opt, "zrfd")) { - if (param != NULL) { - return ERR_OUT_OF_RANGE; - } - zr->fd = 1; - return 1; - } else if (!strcasecmp(opt, "zrcrop")){ - geo_t *g = &zr->g; - if (g->set == 1) { - zr_parsing++; - zr_count++; - zr = &zr_info[zr_parsing]; - g = &zr->g; - if (zr_count > 4) { - mp_msg(MSGT_VO, MSGL_ERR, "zr: too many simultaneus display devices requested (max. is 4)\n"); - return ERR_OUT_OF_RANGE; - } - } - if (param == NULL) return ERR_MISSING_PARAM; - if (sscanf(param, "%dx%d+%d+%d", &g->width, &g->height, - &g->xoff, &g->yoff) != 4) { - g->xoff = 0; g->yoff = 0; - if (sscanf(param, "%dx%d", &g->width, &g->height) != 2) { - mp_msg(MSGT_VO, MSGL_ERR, "zr: argument to -zrcrop must be of the form 352x288+16+0\n"); - return ERR_OUT_OF_RANGE; - } - } - g->set = 1; - mp_msg(MSGT_VO, MSGL_V, "zr: cropping %s\n", param); - return 1; - }else if (!strcasecmp(opt, "zrhdec")) { - i = atoi(param); - if (i != 1 && i != 2 && i != 4) return ERR_OUT_OF_RANGE; - zr->hdec = i; - return 1; - }else if (!strcasecmp(opt, "zrvdec")) { - i = atoi(param); - if (i != 1 && i != 2 && i != 4) return ERR_OUT_OF_RANGE; - zr->vdec = i; - return 1; - }else if (!strcasecmp(opt, "zrxdoff")) { - i = atoi(param); - zr->xdoff = i; - return 1; - }else if (!strcasecmp(opt, "zrydoff")) { - i = atoi(param); - zr->ydoff = i; - return 1; - }else if (!strcasecmp(opt, "zrquality")) { - i = atoi(param); - if (i < 1 || i > 20) return ERR_OUT_OF_RANGE; - zr->quality = i; - return 1; - }else if (!strcasecmp(opt, "zrnorm")) { - if (param == NULL) return ERR_MISSING_PARAM; - if (!strcasecmp(param, "NTSC")) { - mp_msg(MSGT_VO, MSGL_V, "zr: Norm set to NTSC\n"); - zr->norm = VIDEO_MODE_NTSC; - return 1; - } else if (!strcasecmp(param, "PAL")) { - mp_msg(MSGT_VO, MSGL_V, "zr: Norm set to PAL\n"); - zr->norm = VIDEO_MODE_PAL; - return 1; - } else { - return ERR_OUT_OF_RANGE; - } - }else if (!strcasecmp(opt, "zrhelp")){ - printf("Help for -vo zr: Zoran ZR360[56]7/ZR36060 based MJPEG capture/playback cards\n"); - printf("\n"); - printf("Here are the zr options:\n"); - printf( - "\n" - " -zrcrop specify part of the input image that\n" - " you want to see as an x-style geometry string\n" - " example: -zrcrop 352x288+16+0\n" - " -zrvdec vertical decimation 1, 2 or 4\n" - " -zrhdec horizontal decimation 1, 2 or 4\n" - " -zrfd decimation is only done if the primitive\n" - " hardware upscaler can correct for the decimation,\n" - " this switch allows you to see the effects\n" - " of too much decimation\n" - " -zrbw display in black&white (speed increase)\n" - " -zrxdoff x offset from upper-left of TV screen (default is 'centered')\n" - " -zrydoff y offset from upper-left of TV screen (default is 'centered')\n" - " -zrquality jpeg compression quality [BEST] 1 - 20 [VERY BAD]\n" - " -zrdev playback device (example -zrdev /dev/video1)\n" - " -zrnorm specify norm PAL/NTSC (default: leave at current setting)\n" - "\n" - "Cinerama support: additional occurances of -zrcrop activate cinerama mode,\n" - "suppose you have a 704x272 movie, two DC10+ cards and two beamers (or tv's),\n" - "then you would issue the following command:\n\n" - "mplayer -vo zr -zrcrop 352x272+0+0 -zrdev /dev/video0 -zrcrop 352x272+352+0 \\\n" - " -zrdev /dev/video1 movie.avi\n\n" - "Options appearing after the second -zrcrop apply to the second card, it is\n" - "possible to dispay at a different jpeg quality or at different decimations.\n\n" - "The parameters -zrxdoff and -zrydoff can be used to align the two images.\n" - "The maximum number of zoran cards participating in cinerama is 4, so you can\n" - "build a 2x2 vidiwall. (untested for obvious reasons, the setup wit a buz and\n" - "a DC10+ (and no beamers) is tested, however)\n" - ); - exit(0); - - } - return ERR_NOT_AN_OPTION; -} - -void vo_zr_revertoption(const m_option_t* opt,const char* param) { - - zr_info_t *zr = &zr_info[1]; - zr_count = 1; - zr_parsing = 0; - - if (!strcasecmp(param, "zrdev")) { - free(zr->device); - zr->device=NULL; - } else if (!strcasecmp(param, "zrbw")) - zr->bw=0; - else if (!strcasecmp(param, "zrfd")) - zr->fd=0; - else if (!strcasecmp(param, "zrcrop")) - zr->g.set = zr->g.xoff = zr->g.yoff = 0; - else if (!strcasecmp(param, "zrhdec")) - zr->hdec = 1; - else if (!strcasecmp(param, "zrvdec")) - zr->vdec = 1; - else if (!strcasecmp(param, "zrxdoff")) - zr->xdoff = -1; - else if (!strcasecmp(param, "zrydoff")) - zr->ydoff = -1; - else if (!strcasecmp(param, "zrquality")) - zr->quality = 2; - else if (!strcasecmp(param, "zrnorm")) - zr->norm = VIDEO_MODE_AUTO; - -} - -static int preinit(const char *arg) -{ - if(arg) - { - printf("vo_zr: Unknown subdevice: %s\n",arg); - return ENOSYS; - } - return 0; -} - -static int control(uint32_t request, void *data) -{ - switch (request) { - case VOCTRL_QUERY_FORMAT: - return query_format(*((uint32_t*)data)); - } - return VO_NOTIMPL; -} |