[MPlayer-dev-eng] [PATCH] DC10+ (and alike) TV-Out support (fwd)
Alex Beregszaszi
alex at naxine.org
Fri Jan 18 13:16:07 CET 2002
Hi,
Are these Zoran chips only supporting mjpeg? If not, have a look at
main/RTjpegN.c
--
alex
On Wed, Jan 16, 2002 at 05:25:04PM +0100, Rik Snel wrote:
> Sorry,
>
> I forgot to attach the patch.... Here it is now.
>
> Greetings,
>
> Rik
>
> --------
> Nothing is ever a total loss; it can always serve as a bad example.
> diff -Naur main/Makefile main.dev/Makefile
> --- main/Makefile Wed Jan 16 09:08:21 2002
> +++ main.dev/Makefile Wed Jan 16 09:15:11 2002
> @@ -41,7 +41,7 @@
> VO_LIBS = -Llibvo -lvo
> VO_INC = -Ilibvo
> endif
> -V_LIBS = $(X_LIB) $(MP1E_LIB) $(GGI_LIB) $(MLIB_LIB) $(PNG_LIB) $(SDL_LIB) $(SVGA_LIB) $(AA_LIB) $(DIRECTFB_LIB)
> +V_LIBS = $(X_LIB) $(MP1E_LIB) $(GGI_LIB) $(MLIB_LIB) $(JPEG_LIB) $(PNG_LIB) $(SDL_LIB) $(SVGA_LIB) $(AA_LIB) $(DIRECTFB_LIB)
>
> AO_LIBS = -Llibao2 -lao2
> A_LIBS = $(ALSA_LIB) $(NAS_LIB) $(MAD_LIB) $(VORBIS_LIB) $(SGIAUDIO_LIB)
> diff -Naur main/cfg-mplayer.h main.dev/cfg-mplayer.h
> --- main/cfg-mplayer.h Wed Jan 16 09:08:29 2002
> +++ main.dev/cfg-mplayer.h Wed Jan 16 09:55:43 2002
> @@ -65,6 +65,10 @@
> extern int vo_aa_parseoption(struct config * conf, char *opt, char * param);
> #endif
>
> +#ifdef HAVE_ZR
> +extern int vo_zr_parseoption(struct config * conf, char *opt, char * param);
> +#endif
> +
> #ifdef HAVE_NEW_GUI
> extern char * skinName;
> #endif
> @@ -237,6 +241,10 @@
>
> #ifdef HAVE_AA
> {"aa*", vo_aa_parseoption, CONF_TYPE_FUNC_FULL, 0, 0, 0 , NULL},
> +#endif
> +
> +#ifdef HAVE_ZR
> + {"zr*", vo_zr_parseoption, CONF_TYPE_FUNC_FULL, 0, 0, 0 },
> #endif
>
> #ifdef HAVE_LIRC
> diff -Naur main/configure main.dev/configure
> --- main/configure Wed Jan 16 09:08:30 2002
> +++ main.dev/configure Wed Jan 16 09:15:11 2002
> @@ -153,6 +153,7 @@
> --enable-3dfx build with 3dfx support [disable]
> --enable-tdfxfb build with tdfxfb support [disable]
> --enable-directfb build with DirectFB support [autodetect]
> + --enable-zr build with ZR36067/ZR36060 support [disable]
>
> Audio:
> --disable-ossaudio disable OSS sound support [autodetect]
> @@ -672,6 +673,7 @@
> _xv=auto
> _sdl=auto
> _nas=auto
> +_jpeg=auto
> _png=auto
> _gl=auto
> _ggi=auto
> @@ -712,6 +714,7 @@
> _3dfx=no
> _tdfxfb=no
> _directfb=auto
> +_zr=no
> _largefiles=no
> _vo2=no
> _language=en
> @@ -742,6 +745,8 @@
> --disable-sdl) _sdl=no ;;
> --enable-nas) _nas=yes ;;
> --disable-nas) _nas=no ;;
> + --enable-jpeg) _jpeg=yes ;;
> + --disable-jpeg) _jpeg=no ;;
> --enable-png) _png=yes ;;
> --disable-png) _png=no ;;
> --enable-gl) _gl=yes ;;
> @@ -818,6 +823,8 @@
> --disable-tdfxfb) _tdfxfb=no ;;
> --enable-directfb) _directfb=yes ;;
> --disable-directfb) _directfb=no ;;
> + --enable-zr) _zr=yes ;;
> + --disable-zr) _zr=no ;;
> --enable-mtrr) _mtrr=yes ;;
> --disable-mtrr) _mtrr=no ;;
> --enable-largefiles) _largefiles=yes ;;
> @@ -1805,6 +1812,34 @@
> fi
> echores "$_dvb"
>
> +echocheck "JPEG support"
> +if test "$_jpeg" = auto; then
> + _jpeg=no
> +cat > $TMPC << EOF
> +#include <stdio.h>
> +#include <jpeglib.h>
> +int main(void) { return 0; }
> +EOF
> + cc_check -ljpeg && _jpeg=yes
> +fi
> +echores "$_jpeg"
> +
> +echocheck "zr"
> +if test "$_zr" = yes ; then
> + if test "$_jpeg" = yes ; then
> + _ld_jpeg='-ljpeg'
> + _def_zr='#define HAVE_ZR 1'
> + _vosrc="$_vosrc vo_zr.c"
> + _vomodules="zr $_vomodules"
> + echores "$_zr"
> + else
> + echores "jpeglib is required by zr, sorry"
> + _def_zr='#undef HAVE_ZR'
> + fi
> +else
> + _def_zr='#undef HAVE_ZR'
> + echores "$_zr"
> +fi
>
> echocheck "PNG support"
> if test "$_png" = auto ; then
> @@ -2780,7 +2815,7 @@
> CC = $_cc
> AWK = $_awk
> # OPTFLAGS = -O4 $_profile $_debug $_march $_mcpu -pipe -fomit-frame-pointer -ffast-math
> -OPTFLAGS = $CFLAGS
> +OPTFLAGS = -Djpeg_fdct_ifast=jpeg_fdct_ifast2 $CFLAGS
> EXTRA_INC = $_inc_extra $_inc_gtk
> WIN32_PATH = -DWIN32_PATH=\\"$_win32libdir\\"
>
> @@ -2803,6 +2838,7 @@
> GGI_LIB = $_ld_ggi
> MLIB_LIB = $_ld_mlib
> MLIB_INC = $_inc_mlib
> +JPEG_LIB = $_ld_jpeg
> PNG_LIB = $_ld_png
> SDL_LIB = $_ld_sdl
> SVGA_LIB = $_ld_svga
> @@ -3120,6 +3156,7 @@
> $_def_3dfx
> $_def_tdfxfb
> $_def_directfb
> +$_def_zr
> $_def_mga
> $_def_xmga
> $_def_syncfb
> --- main/libvo/video_out.c Wed Jan 16 09:09:22 2002
> +++ main.dev/libvo/video_out.c Wed Jan 16 09:15:11 2002
> @@ -64,6 +64,7 @@
> extern vo_functions_t video_out_tdfxfb;
> extern vo_functions_t video_out_null;
> //extern vo_functions_t video_out_odivx;
> +extern vo_functions_t video_out_zr;
> extern vo_functions_t video_out_pgm;
> extern vo_functions_t video_out_md5;
> extern vo_functions_t video_out_syncfb;
> @@ -130,6 +131,9 @@
> #endif
> #ifdef HAVE_DXR3
> &video_out_dxr3,
> +#endif
> +#ifdef HAVE_ZR
> + &video_out_zr,
> #endif
>
> #ifdef HAVE_PNG
> diff -Naur main/libvo/vo_zr.c main.dev/libvo/vo_zr.c
> --- main/libvo/vo_zr.c Thu Jan 1 01:00:00 1970
> +++ main.dev/libvo/vo_zr.c Wed Jan 16 09:58:19 2002
> @@ -0,0 +1,642 @@
> +/*
> + * vo_zr.c - playback on zoran cards
> + * Copyright (C) Rik Snel 2001,2002, License GNU GPL v2
> + */
> +
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <unistd.h>
> +#include <fcntl.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 "zoran.h"
> +
> +#include "config.h"
> +#define ZR_USES_LIBJPEG
> +
> +#include "video_out.h"
> +#include "video_out_internal.h"
> +#include "../mp_msg.h"
> +#include "../cfgparser.h"
> +
> +LIBVO_EXTERN (zr)
> +
> +static vo_info_t vo_info =
> +{
> + "Zoran ZR360[56]7/ZR36060 Driver (DC10(+)/buz/lml33/MatroxRR)",
> + "zr",
> + "Rik Snel <snel at phys.uu.nl>",
> + ""
> +};
> +
> +/* General variables */
> +
> +static int image_width;
> +static int image_height;
> +static int off_y, off_c, stride; /* for use by 'draw slice' */
> +static int framenum;
> +static int fields = 1; /* currently no interlacing */
> +static int forceinter = 0;
> +static int vdec = 1;
> +static int size;
> +static int quality = 70;
> +
> +typedef struct {
> + int width;
> + int height;
> + int xoff;
> + int yoff;
> + int set;
> +} geo;
> +geo g = {0, 0, 0, 0, 0};
> +
> +static uint8_t *image=NULL;
> +static uint8_t *buf=NULL;
> +
> +
> +/* Variables needed for Zoran */
> +
> +int vdes; /* the file descriptor of the video device */
> +int frame = 0, synco = 0, queue = 0; /* buffer management */
> +struct zoran_params zp;
> +struct zoran_requestbuffers zrq;
> +struct zoran_sync zs;
> +struct video_capability vc;
> +#define MJPEG_NBUFFERS 2
> +#define MJPEG_SIZE 1024*256
> +
> +//should be command line options
> +int norm = VIDEO_MODE_AUTO;
> +char *device = "/dev/video";
> +
> +
> +#ifdef ZR_USES_LIBJPEG
> +#include<jpeglib.h>
> +int ccount;
> +unsigned char *ccbuf;
> +struct jpeg_compress_struct cinfo;
> +struct jpeg_destination_mgr jdest;
> +struct jpeg_error_mgr jerr;
> +
> +/* minimal destination handler to output to buffer */
> +METHODDEF(void) init_destination(struct jpeg_compress_struct *cinfo) {
> +// printf("init_destination called %p %d\n", ccbuf, ccount);
> + cinfo->dest->next_output_byte = (JOCTET*)(ccbuf+ccount);
> + cinfo->dest->free_in_buffer = MJPEG_SIZE - ccount;
> +}
> +
> +METHODDEF(boolean) empty_output_buffer(struct jpeg_compress_struct *cinfo) {
> +// printf("empty_output_buffer called\n");
> + mp_msg(MSGT_VO, MSGL_ERR, "empty_output_buffer called, may not happen because buffer must me large enough\n");
> + return(FALSE);
> +}
> +
> +METHODDEF(void) term_destination(struct jpeg_compress_struct *cinfo) {
> +// printf("term_destination called %p %d\n", ccbuf, ccount);
> + ccount = MJPEG_SIZE - cinfo->dest->free_in_buffer;
> +}
> +/* end of minimal destination handler */
> +
> +JSAMPARRAY ***jsi;
> +
> +#else
> +#include "../libavcodec/avcodec.h"
> +AVCodec *codec;
> +AVCodecContext codec_context;
> +AVPicture picture;
> +#endif
> +
> +static int jpegdct = JDCT_IFAST;
> +
> +int init_codec() {
> +#ifdef ZR_USES_LIBJPEG
> + int i, j, k;
> + cinfo.err = jpeg_std_error(&jerr);
> + jpeg_create_compress(&cinfo);
> +
> + cinfo.dest = &jdest;
> + cinfo.dest->init_destination = init_destination;
> + cinfo.dest->empty_output_buffer = empty_output_buffer;
> + cinfo.dest->term_destination = term_destination;
> +
> + cinfo.input_components = 3;
> +
> + jpeg_set_defaults(&cinfo);
> +
> + cinfo.image_width = image_width;
> + cinfo.image_height = image_height/fields;
> + cinfo.input_gamma = 1.0;
> + cinfo.in_color_space = JCS_YCbCr;
> + cinfo.raw_data_in = TRUE;
> + cinfo.comp_info[0].h_samp_factor = 2;
> + cinfo.comp_info[0].v_samp_factor = 1;
> + cinfo.comp_info[1].h_samp_factor = 1;
> + cinfo.comp_info[1].v_samp_factor = 1;
> + cinfo.comp_info[2].h_samp_factor = 1;
> + cinfo.comp_info[2].v_samp_factor = 1;
> + cinfo.dct_method = jpegdct;
> + jpeg_set_quality(&cinfo, quality, FALSE);
> + jsi = malloc(sizeof(JSAMPARRAY**)*fields);
> +
> + /* Just some clutter to give libjpeg the pointers,
> + * and I don't want to recalculate everything everytime
> + * it is needed */
> + for (k = 0; k < fields; k++) {
> + jsi[k] = malloc(sizeof(JSAMPARRAY*)*image_height/(8*fields));
> +
> + for (i = 0; i < image_height/(8*fields); i++) {
> + jsi[k][i] = malloc(3*sizeof(JSAMPARRAY));
> + jsi[k][i][0] = malloc(8*sizeof(JSAMPROW));
> + jsi[k][i][1] = malloc(8*sizeof(JSAMPROW));
> + jsi[k][i][2] = malloc(8*sizeof(JSAMPROW));
> + for (j = 0; j < 8; j++) {
> + jsi[k][i][0][j] = (JSAMPROW)(image +
> + (fields*(8*i + j) + k)*image_width);
> + jsi[k][i][1][j] = (JSAMPROW)(image + size +
> + (fields*(8*i + j)/2)*image_width/2);
> + jsi[k][i][2][j] = (JSAMPROW)(image + 3*size/2 +
> + (fields*(8*i + j)/2)*image_width/2);
> + }
> + }
> +
> + }
> +#else
> + AVCodecContext *c = &codec_context;
> + codec = avcodec_find_encoder(CODEC_ID_MJPEG);
> + if (!codec) {
> + /* maybe libavcodec was not initialized */
> + avcodec_init();
> + avcodec_register_all();
> + codec = avcodec_find_encoder(CODEC_ID_MJPEG);
> + if (!codec) {
> + mp_msg(MSGT_VO, MSGL_ERR, "MJPG codec not found in libavcodec\n");
> + return 1;
> + }
> + }
> + /* put default values */
> + memset(c, 0, sizeof(*c));
> +
> + c->width = image_width;
> + c->height = image_height;
> + c->bit_rate = 4000000;
> + c->frame_rate = 25*FRAME_RATE_BASE;
> + //c->gop_size = 1;
> + c->pix_fmt = PIX_FMT_YUV422P;
> +
> + if (avcodec_open(c, codec) < 0) {
> + mp_msg(MSGT_VO, MSGL_ERR, "MJPG codec could not be opened\n");
> + return 1;
> + }
> +
> + picture.data[0] = image;
> + picture.data[1] = image + size;
> + picture.data[2] = image + 3*size/2;
> + picture.linesize[0] = image_width;
> + picture.linesize[1] = image_width/2;
> + picture.linesize[2] = image_width/2;
> +#endif
> + return 0;
> +}
> +
> +
> +int zoran_getcap() {
> + vdes = open(device, O_RDWR);
> + /* before we can ask for the maximum resolution, we must set
> + * the correct tv norm */
> +
> + if (ioctl(vdes, BUZIOC_G_PARAMS, &zp) < 0) {
> + mp_msg(MSGT_VO, MSGL_ERR, "device at %s is probably not a DC10(+)/buz/lml33\n", device);
> + return 1;
> + }
> +
> + if (zp.norm != norm && norm != VIDEO_MODE_AUTO) {
> + /* attempt to set requested norm */
> + zp.norm = norm;
> + if (ioctl(vdes, BUZIOC_S_PARAMS, &zp) < 0) {
> + mp_msg(MSGT_VO, MSGL_ERR,
> + "unable to change video norm, use another program to change it (XawTV)\n");
> + return 1;
> + }
> + ioctl(vdes, BUZIOC_G_PARAMS, &zp);
> + if (norm != zp.norm) {
> + mp_msg(MSGT_VO, MSGL_ERR,
> + "unable to change video norm, use another program to change it (XawTV)\n");
> + return 1;
> + }
> + }
> +
> + if (vdes < 0) {
> + mp_msg(MSGT_VO, MSGL_ERR, "error opening %s\n",
> + device);
> + return 1;
> + }
> +
> +
> + if (ioctl(vdes, VIDIOCGCAP, &vc) < 0) {
> + mp_msg(MSGT_VO, MSGL_ERR, "error getting video capabilities from %s\n");
> + return 1;
> + }
> + mp_msg(MSGT_VO, MSGL_V, "zr36067 reports: maxwidth=%d, maxheight=%d\n", vc.maxwidth, vc.maxheight);
> +
> + return 0;
> +}
> +
> +int init_zoran() {
> + /* center the image, and stretch it as far as possible (try to keep
> + * aspect) and check if it fits */
> + if (image_width > vc.maxwidth) {
> + mp_msg(MSGT_VO, MSGL_ERR, "movie to be played is too wide, max width currenty %d\n", vc.maxwidth);
> + return 1;
> + }
> +
> + if (image_height > vc.maxheight) {
> + mp_msg(MSGT_VO, MSGL_ERR, "movie to be played is too high, max height currenty %d\n", vc.maxheight);
> + return 1;
> + }
> +
> + zp.decimation = 0;
> + zp.HorDcm = (vc.maxwidth >= 2*(int)image_width) ? 2 : 1;
> + zp.VerDcm = 1;
> + if (zp.HorDcm == 2 && 4*image_width <= vc.maxwidth &&
> + 4*image_height/fields <= vc.maxheight) {
> + zp.HorDcm = 4;
> + zp.VerDcm = 2;
> + }
> + if (((forceinter == 0 && vdec >= 2) || (forceinter == 1 && vdec == 4)) && 4*image_height/fields <= vc.maxheight) {
> + zp.VerDcm = 2;
> + }
> + zp.TmpDcm = 1;
> + zp.field_per_buff = fields;
> + zp.img_x = (vc.maxwidth - zp.HorDcm*(int)image_width)/2;
> + zp.img_y = (vc.maxheight - zp.VerDcm*(3-fields)*(int)image_height)/4;
> + zp.img_width = zp.HorDcm*image_width;
> + zp.img_height = zp.VerDcm*image_height/fields;
> + mp_msg(MSGT_VO, MSGL_V, "zr: geometry (after 'scaling'): %dx%d+%d+%d fields=%d, w=%d, h=%d\n", zp.img_width, zp.img_height, zp.img_x, zp.img_y, fields, image_width, image_height);
> +
> + if (ioctl(vdes, BUZIOC_S_PARAMS, &zp) < 0) {
> + mp_msg(MSGT_VO, MSGL_ERR, "error setting display parameters\n");
> + return 1;
> + }
> +
> + zrq.count = MJPEG_NBUFFERS;
> + zrq.size = MJPEG_SIZE;
> +
> + if (ioctl(vdes, BUZIOC_REQBUFS, &zrq)) {
> + mp_msg(MSGT_VO, MSGL_ERR, "error requesting %d buffers of size %d\n", zrq.count, zrq.size);
> + return 1;
> + }
> +
> + buf = (char*)mmap(0, zrq.count*zrq.size, PROT_READ|PROT_WRITE,
> + MAP_SHARED, vdes, 0);
> +
> + if (buf == MAP_FAILED) {
> + mp_msg(MSGT_VO, MSGL_ERR, "error requesting %d buffers of size %d\n", zrq.count, zrq.size);
> + return 1;
> + }
> + return 0;
> +}
> +
> +void uninit_zoran(void) {
> + if (image) {
> + free(image);
> + image=NULL;
> + }
> + while (queue > synco + 1) {
> + if (ioctl(vdes, BUZIOC_SYNC, &zs) < 0)
> + mp_msg(MSGT_VO, MSGL_ERR, "error waiting for buffers to become free");
> + synco++;
> + }
> + /* stop streaming */
> + frame = -1;
> + if (ioctl(vdes, BUZIOC_QBUF_PLAY, &frame) < 0)
> + mp_msg(MSGT_VO, MSGL_ERR, "error stopping playback of last frame");
> + close(vdes);
> +}
> +
> +static uint32_t init(uint32_t width, uint32_t height, uint32_t d_width,
> + uint32_t d_height, uint32_t fullscreen, char *title, uint32_t format)
> +{
> + int j;
> + /* this allows to crop parts from incoming picture,
> + * for easy 512x240 -> 352x240 */
> + /* These values must be multples of 2 */
> +
> + 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, "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, "width and height must be positive and offset nonnegative\n");
> + return 1;
> + }
> + if (g.width + g.xoff > width) {
> + mp_msg(MSGT_VO, MSGL_ERR, "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, "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;
> + }
> + /* we must know the maximum resolution of the device
> + * it differs for DC10+ and buz for example */
> + zoran_getcap(); /*must be called before init_zoran */
> + if (g.height/vdec > vc.maxheight/2 || (forceinter == 1 && vdec == 1))
> + fields = 2;
> + printf("fields=%d\n", fields);
> + /* 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*/
> + image_height = fields*8*((g.height/vdec - 1)/(fields*8) + 1);
> + image_width = 16*((g.width - 1)/16 + 1);
> + off_y = (image_height - g.height/vdec)/2;
> + if (off_y%2 != 0) off_y++;
> + off_y *= image_width;
> + off_c = off_y/4;
> + off_y += (image_width - g.width)/2;
> + if (off_y%2 != 0) off_y--;
> + off_c += (image_width - g.width)/4;
> + framenum = 0;
> + size = image_width*image_height;
> + mp_msg(MSGT_VO, MSGL_V, "input: %dx%d, cropped: %dx%d, output: %dx%d, off_y=%d, off_c=%d\n", width, height, g.width, g.height, image_width, image_height, off_y, off_c);
> +
> + image = malloc(2*size); /* this buffer allows for YUV422 data,
> + * so it is a bit too big for YUV420 */
> + if (!image) {
> + mp_msg(MSGT_VO, MSGL_ERR, "Memory exhausted\n");
> + return 1;
> + }
> + /* and make sure that the borders are _really_ black */
> + memset(image, 0, image_width*image_height);
> + memset(image + size, 0x80, image_width*image_height/4);
> + memset(image + 3*size/2, 0x80, image_width*image_height/4);
> +
> + if (init_codec()) {
> + return 1;
> + }
> +
> + if (init_zoran()) {
> +#ifdef ZR_USES_LIBJPEG
> + jpeg_destroy_compress(&cinfo);
> +#else
> + avcodec_close(&codec_context);
> +#endif
> + return 1;
> + }
> +
> + return 0;
> +}
> +
> +static const vo_info_t* get_info(void) {
> + return &vo_info;
> +}
> +
> +static void draw_osd(void) {
> +}
> +
> +static void flip_page (void) {
> +#ifdef ZR_USES_LIBJPEG
> + int i, j, k;
> +#else
> + AVCodecContext *c = &codec_context;
> +#endif
> +
> + /* do we have a free buffer? */
> + if (queue-synco < zrq.count) {
> + frame = queue;
> + } else {
> + if (ioctl(vdes, BUZIOC_SYNC, &zs) < 0)
> + mp_msg(MSGT_VO, MSGL_ERR, "error waiting for buffers to become free");
> + frame = zs.frame;
> + synco++;
> + }
> +
> +#ifdef ZR_USES_LIBJPEG
> + ccbuf = buf + frame*zrq.size;
> + ccount = 0;
> + k = fields;
> + for (j=0; j < k; j++) {
> +
> + jpeg_start_compress(&cinfo, TRUE);
> + i=0;
> + while (cinfo.next_scanline < cinfo.image_height) {
> + jpeg_write_raw_data(&cinfo, jsi[j][i], 8);
> + i++;
> + }
> + jpeg_finish_compress(&cinfo);
> +
> + }
> +#else
> + avcodec_encode_video(c, buf + frame*zrq.size, MJPEG_SIZE, &picture);
> +#endif
> +
> + if (ioctl(vdes, BUZIOC_QBUF_PLAY, &frame) < 0)
> + mp_msg(MSGT_VO, MSGL_ERR,
> + "error queueing buffer for playback");
> + queue++;
> +
> + framenum++;
> + return;
> +}
> +
> +static uint32_t draw_frame(uint8_t * src[]) {
> + return 0;
> +}
> +
> +static uint32_t query_format(uint32_t format) {
> + if(format==IMGFMT_YV12) return 1;
> + return 0;
> +}
> +
> +static void uninit(void) {
> + uninit_zoran();
> +
> +#ifdef ZR_USES_LIBJPEG
> + jpeg_destroy_compress(&cinfo);
> +#else
> + avcodec_close(&codec_context);
> +#endif
> +}
> +
> +static void check_events(void) {
> +}
> +
> +
> +static uint32_t draw_slice(uint8_t *srcimg[], int stride[],
> + int w, int h, int x, int y) {
> + int i;
> + /* Apply 'geometry', crop unwanted parts */
> + uint8_t *dst;
> + uint8_t *src;
> + //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]);
> + if (x < g.xoff) {
> + srcimg[0] += g.xoff - x;
> + srcimg[1] += (g.xoff - x)/2;
> + srcimg[2] += (g.xoff - x)/2;
> + w -= g.xoff - x;
> + if (w < 0) return 0;
> + x = 0 /*g.xoff*/;
> + } else {
> + x -= g.xoff;
> + }
> + if (x + w > g.width) {
> + w = g.width - x;
> + if (w < 0) return 0;
> + }
> + if (y < g.yoff) {
> + srcimg[0] += (g.yoff - y)*stride[0];
> + srcimg[1] += ((g.yoff - y)/2)*stride[1];
> + srcimg[2] += ((g.yoff - y)/2)*stride[2];
> + h -= g.yoff - y;
> + if (h < 0) return 0;
> + y = 0;
> + } else {
> + y -= g.yoff;
> + }
> + if (y + h > g.height) {
> + h = g.height - y;
> + if (h < 0) 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=image + off_y + image_width*(y/vdec)+x;
> + src=srcimg[0];
> + // copy Y:
> + for (i = 0; i < h; i++) {
> + if ((i + x)%vdec == 0) {
> + memcpy(dst,src,w);
> + dst+=image_width;
> + }
> + src+=stride[0];
> +
> + }
> + {
> + // copy U+V:
> + uint8_t *src1=srcimg[1];
> + uint8_t *src2=srcimg[2];
> + uint8_t *dst1=image + size + off_c+ (y/(vdec*2))*image_width/2+(x/2);
> + uint8_t *dst2=image + 3*size/2 + off_c +
> + (y/(vdec*2))*image_width/2+(x/2);
> + for (i = 0; i< h/2; i++) {
> + if ((i+x/2)%vdec == 0) {
> + memcpy(dst1,src1,w/2);
> + memcpy(dst2,src2,w/2);
> + dst1+=image_width/2;
> + dst2+=image_width/2;
> + }
> + src1+=stride[1];
> + src2+=stride[2];
> + }
> + }
> + return 0;
> +}
> +
> +
> +/* copied and adapted from vo_aa_parseoption */
> +int
> +vo_zr_parseoption(struct config * conf, char *opt, char *param){
> + /* got an option starting with zr */
> + char *x, *help;
> + 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;
> + device = malloc(strlen(param)+1);
> + strcpy(device, param);
> + mp_msg(MSGT_VO, MSGL_V, "zr: using device %s\n", device);
> + return 1;
> + } else if (!strcasecmp(opt, "zrfi")) {
> + if (param != NULL) {
> + return ERR_OUT_OF_RANGE;
> + }
> + forceinter = 1;
> + return 1;
> + } else if (!strcasecmp(opt, "zrcrop")){
> + 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, "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, "zrvdec")) {
> + i = atoi(param);
> + if (i != 1 && i != 2 && i != 4) return ERR_OUT_OF_RANGE;
> + vdec = i;
> + return 1;
> + }else if (!strcasecmp(opt, "zrquality")) {
> + i = atoi(param);
> + if (i < 30 || i > 100) return ERR_OUT_OF_RANGE;
> + quality = i;
> + return 1;
> + }else if (!strcasecmp(opt, "zrdct")) {
> + if (param == NULL) return ERR_MISSING_PARAM;
> + if (!strcasecmp(param, "IFAST")) {
> + jpegdct = JDCT_IFAST;
> + return 1;
> + } else if (!strcasecmp(param, "ISLOW")) {
> + jpegdct = JDCT_ISLOW;
> + return 1;
> + } else if (!strcasecmp(param, "FLOAT")) {
> + jpegdct = JDCT_FLOAT;
> + return 1;
> + } else {
> + return ERR_OUT_OF_RANGE;
> + }
> + }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");
> + norm = VIDEO_MODE_NTSC;
> + return 1;
> + } else if (!strcasecmp(param, "PAL")) {
> + mp_msg(MSGT_VO, MSGL_V, "zr: Norm set to PAL\n");
> + 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"
> + " -zrfi force interlacing ('wide screen')\n"
> + " (by default we only interlace if the movie\n"
> + " is higher than half of the screen height)\n"
> + " -zrquality jpeg compression quality 30-100\n"
> + " -zrdct specify DCT method: IFAST, ISLOW or FLOAT\n"
> + " -zrdev playback device (example -zrdev /dev/video1\n"
> + " -zrnorm specify norm PAL/NTSC [dev: leave at current setting]\n"
> + "\n"
> + );
> + exit(0);
> +
> + }
> + return ERR_NOT_AN_OPTION;
> +}
> diff -Naur main/libvo/zoran.h main.dev/libvo/zoran.h
> --- main/libvo/zoran.h Thu Jan 1 01:00:00 1970
> +++ main.dev/libvo/zoran.h Wed Jan 16 09:15:11 2002
> @@ -0,0 +1,372 @@
> +/*
> + zoran - Iomega Buz driver
> +
> + Copyright (C) 1999 Rainer Johanni <Rainer at Johanni.de>
> +
> + based on
> +
> + zoran.0.0.3 Copyright (C) 1998 Dave Perks <dperks at ibm.net>
> +
> + and
> +
> + bttv - Bt848 frame grabber driver
> + Copyright (C) 1996,97 Ralph Metzler (rjkm at thp.uni-koeln.de)
> +
> + This program 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.
> +
> + This program 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 this program; if not, write to the Free Software
> + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> +*/
> +
> +#ifndef _BUZ_H_
> +#define _BUZ_H_
> +
> +#include <linux/config.h>
> +
> +#if LINUX_VERSION_CODE < 0x20212
> +typedef struct wait_queue *wait_queue_head_t;
> +#endif
> +
> +/* The Buz only supports a maximum width of 720, but some V4L
> + applications (e.g. xawtv are more happy with 768).
> + If XAWTV_HACK is defined, we try to fake a device with bigger width */
> +
> +//#define XAWTV_HACK
> +
> +//#ifdef XAWTV_HACK
> +//#define BUZ_MAX_WIDTH 768 /* never display more than 768 pixels */
> +#define BUZ_MAX_WIDTH (zr->timing->Wa)
> +//#else
> +//#define BUZ_MAX_WIDTH 720 /* never display more than 720 pixels */
> +//#endif
> +//#define BUZ_MAX_HEIGHT 576 /* never display more than 576 rows */
> +#define BUZ_MAX_HEIGHT (zr->timing->Ha)
> +#define BUZ_MIN_WIDTH 32 /* never display less than 32 pixels */
> +#define BUZ_MIN_HEIGHT 24 /* never display less than 24 rows */
> +
> +struct zoran_requestbuffers {
> + unsigned long count; /* Number of buffers for MJPEG grabbing */
> + unsigned long size; /* Size PER BUFFER in bytes */
> +};
> +
> +struct zoran_sync {
> + unsigned long frame; /* number of buffer that has been free'd */
> + unsigned long length; /* number of code bytes in buffer (capture only) */
> + unsigned long seq; /* frame sequence number */
> + struct timeval timestamp; /* timestamp */
> +};
> +
> +struct zoran_status {
> + int input; /* Input channel, has to be set prior to BUZIOC_G_STATUS */
> + int signal; /* Returned: 1 if valid video signal detected */
> + int norm; /* Returned: VIDEO_MODE_PAL or VIDEO_MODE_NTSC */
> + int color; /* Returned: 1 if color signal detected */
> +};
> +
> +struct zoran_params {
> +
> + /* The following parameters can only be queried */
> +
> + int major_version; /* Major version number of driver */
> + int minor_version; /* Minor version number of driver */
> +
> + /* Main control parameters */
> +
> + int input; /* Input channel: 0 = Composite, 1 = S-VHS */
> + int norm; /* Norm: VIDEO_MODE_PAL or VIDEO_MODE_NTSC */
> + int decimation; /* decimation of captured video,
> + enlargement of video played back.
> + Valid values are 1, 2, 4 or 0.
> + 0 is a special value where the user
> + has full control over video scaling */
> +
> + /* The following parameters only have to be set if decimation==0,
> + for other values of decimation they provide the data how the image is captured */
> +
> + int HorDcm; /* Horizontal decimation: 1, 2 or 4 */
> + int VerDcm; /* Vertical decimation: 1 or 2 */
> + int TmpDcm; /* Temporal decimation: 1 or 2,
> + if TmpDcm==2 in capture every second frame is dropped,
> + in playback every frame is played twice */
> + int field_per_buff; /* Number of fields per buffer: 1 or 2 */
> + int img_x; /* start of image in x direction */
> + int img_y; /* start of image in y direction */
> + int img_width; /* image width BEFORE decimation,
> + must be a multiple of HorDcm*16 */
> + int img_height; /* image height BEFORE decimation,
> + must be a multiple of VerDcm*8 */
> +
> + /* --- End of parameters for decimation==0 only --- */
> +
> + /* JPEG control parameters */
> +
> + int quality; /* Measure for quality of compressed images.
> + Scales linearly with the size of the compressed images.
> + Must be beetween 0 and 100, 100 is a compression
> + ratio of 1:4 */
> +
> + int odd_even; /* Which field should come first ??? */
> +
> + int APPn; /* Number of APP segment to be written, must be 0..15 */
> + int APP_len; /* Length of data in JPEG APPn segment */
> + char APP_data[60]; /* Data in the JPEG APPn segment. */
> +
> + int COM_len; /* Length of data in JPEG COM segment */
> + char COM_data[60]; /* Data in JPEG COM segment */
> +
> + unsigned long jpeg_markers; /* Which markers should go into the JPEG output.
> + Unless you exactly know what you do, leave them untouched.
> + Inluding less markers will make the resulting code
> + smaller, but there will be fewer aplications
> + which can read it.
> + The presence of the APP and COM marker is
> + influenced by APP0_len and COM_len ONLY! */
> +#define JPEG_MARKER_DHT (1<<3) /* Define Huffman Tables */
> +#define JPEG_MARKER_DQT (1<<4) /* Define Quantization Tables */
> +#define JPEG_MARKER_DRI (1<<5) /* Define Restart Interval */
> +#define JPEG_MARKER_COM (1<<6) /* Comment segment */
> +#define JPEG_MARKER_APP (1<<7) /* App segment, driver will allways use APP0 */
> +
> + int VFIFO_FB; /* Flag for enabling Video Fifo Feedback.
> + If this flag is turned on and JPEG decompressing
> + is going to the screen, the decompress process
> + is stopped every time the Video Fifo is full.
> + This enables a smooth decompress to the screen
> + but the video output signal will get scrambled */
> +
> + /* Misc */
> +
> + char reserved[312]; /* Makes 512 bytes for this structure */
> +};
> +
> +/*
> +Private IOCTL to set up for displaying MJPEG
> +*/
> +#define BUZIOC_G_PARAMS _IOR ('v', BASE_VIDIOCPRIVATE+0, struct zoran_params)
> +#define BUZIOC_S_PARAMS _IOWR('v', BASE_VIDIOCPRIVATE+1, struct zoran_params)
> +#define BUZIOC_REQBUFS _IOWR('v', BASE_VIDIOCPRIVATE+2, struct zoran_requestbuffers)
> +#define BUZIOC_QBUF_CAPT _IOW ('v', BASE_VIDIOCPRIVATE+3, int)
> +#define BUZIOC_QBUF_PLAY _IOW ('v', BASE_VIDIOCPRIVATE+4, int)
> +#define BUZIOC_SYNC _IOR ('v', BASE_VIDIOCPRIVATE+5, struct zoran_sync)
> +#define BUZIOC_G_STATUS _IOWR('v', BASE_VIDIOCPRIVATE+6, struct zoran_status)
> +
> +
> +#ifdef __KERNEL__
> +
> +#define BUZ_NUM_STAT_COM 4
> +#define BUZ_MASK_STAT_COM 3
> +
> +#define BUZ_MAX_FRAME 256 /* Must be a power of 2 */
> +#define BUZ_MASK_FRAME 255 /* Must be BUZ_MAX_FRAME-1 */
> +
> +#if VIDEO_MAX_FRAME <= 32
> +# define V4L_MAX_FRAME 32
> +#elif VIDEO_MAX_FRAME <= 64
> +# define V4L_MAX_FRAME 64
> +#else
> +# error "Too many video frame buffers to handle"
> +#endif
> +#define V4L_MASK_FRAME (V4L_MAX_FRAME - 1)
> +
> +
> +#include "zr36057.h"
> +
> +enum card_type {
> + UNKNOWN = 0,
> + DC10,
> + DC10plus,
> + LML33,
> + BUZ
> +};
> +
> +enum zoran_codec_mode {
> + BUZ_MODE_IDLE, /* nothing going on */
> + BUZ_MODE_MOTION_COMPRESS, /* grabbing frames */
> + BUZ_MODE_MOTION_DECOMPRESS, /* playing frames */
> + BUZ_MODE_STILL_COMPRESS, /* still frame conversion */
> + BUZ_MODE_STILL_DECOMPRESS /* still frame conversion */
> +};
> +
> +enum zoran_buffer_state {
> + BUZ_STATE_USER, /* buffer is owned by application */
> + BUZ_STATE_PEND, /* buffer is queued in pend[] ready to feed to I/O */
> + BUZ_STATE_DMA, /* buffer is queued in dma[] for I/O */
> + BUZ_STATE_DONE /* buffer is ready to return to application */
> +};
> +
> +struct zoran_gbuffer {
> + u32 *frag_tab; /* addresses of frag table */
> + u32 frag_tab_bus; /* same value cached to save time in ISR */
> + enum zoran_buffer_state state; /* non-zero if corresponding buffer is in use in grab queue */
> + struct zoran_sync bs; /* DONE: info to return to application */
> +};
> +
> +struct v4l_gbuffer {
> + char *fbuffer; /* virtual address of frame buffer */
> + unsigned long fbuffer_phys; /* physical address of frame buffer */
> + unsigned long fbuffer_bus; /* bus address of frame buffer */
> + enum zoran_buffer_state state; /* state: unused/pending/done */
> +};
> +
> +struct tvnorm {
> + u16 Wt, Wa, HStart, HSyncStart, Ht, Ha, VStart;
> +};
> +
> +struct zoran {
> + struct video_device video_dev;
> + struct i2c_bus i2c;
> +
> + int initialized; /* flag if zoran has been correctly initalized */
> + int user; /* number of current users (0 or 1) */
> + enum card_type card;
> + struct tvnorm *timing;
> +
> + unsigned short id; /* number of this device */
> + char name[32]; /* name of this device */
> + struct pci_dev *pci_dev; /* PCI device */
> + unsigned char revision; /* revision of zr36057 */
> + unsigned int zr36057_adr; /* bus address of IO mem returned by PCI BIOS */
> + unsigned char *zr36057_mem; /* pointer to mapped IO memory */
> +
> + int map_mjpeg_buffers; /* Flag which bufferset will map by next mmap() */
> +
> + spinlock_t lock; /* Spinlock irq and hardware */
> + struct semaphore sem; /* Guard parallel ioctls and mmap */
> +
> + /* Video for Linux parameters */
> +
> + struct video_picture picture; /* Current picture params */
> + struct video_buffer buffer; /* Current buffer params */
> + struct video_window window; /* Current window params */
> + int buffer_set, window_set; /* Flags if the above structures are set */
> + int video_interlace; /* Image on screen is interlaced */
> +
> + u32 *overlay_mask;
> + wait_queue_head_t v4l_capq;
> +
> + int v4l_overlay_active; /* Overlay grab is activated */
> + int v4l_memgrab_active; /* Memory grab is activated */
> +
> + int v4l_grab_frame; /* Frame number being currently grabbed */
> +#define NO_GRAB_ACTIVE (-1)
> + int v4l_grab_seq; /* Number of frames grabbed */
> + int gwidth; /* Width of current memory capture */
> + int gheight; /* Height of current memory capture */
> + int gformat; /* Format of ... */
> + int gbpl; /* byte per line of ... */
> +
> + /* V4L grab queue of frames pending */
> +
> + unsigned v4l_pend_head;
> + unsigned v4l_pend_tail;
> + int v4l_pend[V4L_MAX_FRAME];
> +
> + struct v4l_gbuffer v4l_gbuf[VIDEO_MAX_FRAME]; /* V4L buffers' info */
> +
> + /* Buz MJPEG parameters */
> +
> + unsigned long jpg_nbufs; /* Number of buffers */
> + unsigned long jpg_bufsize; /* Size of mjpeg buffers in bytes */
> + int jpg_buffers_allocated; /* Flag if buffers are allocated */
> + int need_contiguous; /* Flag if contiguous buffers are needed */
> +
> + enum zoran_codec_mode codec_mode; /* status of codec */
> + struct zoran_params params; /* structure with a lot of things to play with */
> +
> + wait_queue_head_t jpg_capq; /* wait here for grab to finish */
> +
> + /* grab queue counts/indices, mask with BUZ_MASK_STAT_COM before using as index */
> + /* (dma_head - dma_tail) is number active in DMA, must be <= BUZ_NUM_STAT_COM */
> + /* (value & BUZ_MASK_STAT_COM) corresponds to index in stat_com table */
> + unsigned long jpg_que_head; /* Index where to put next buffer which is queued */
> + unsigned long jpg_dma_head; /* Index of next buffer which goes into stat_com */
> + unsigned long jpg_dma_tail; /* Index of last buffer in stat_com */
> + unsigned long jpg_que_tail; /* Index of last buffer in queue */
> + unsigned long jpg_seq_num; /* count of frames since grab/play started */
> + unsigned long jpg_err_seq; /* last seq_num before error */
> + unsigned long jpg_err_shift;
> + unsigned long jpg_queued_num; /* count of frames queued since grab/play started */
> +
> + /* zr36057's code buffer table */
> + u32 *stat_com; /* stat_com[i] is indexed by dma_head/tail & BUZ_MASK_STAT_COM */
> +
> + /* (value & BUZ_MASK_FRAME) corresponds to index in pend[] queue */
> + int jpg_pend[BUZ_MAX_FRAME];
> +
> + /* array indexed by frame number */
> + struct zoran_gbuffer jpg_gbuf[BUZ_MAX_FRAME]; /* MJPEG buffers' info */
> +
> + /* Additional stuff for testing */
> + struct proc_dir_entry *zoran_proc;
> +
> + int testing;
> + int jpeg_error;
> + int intr_counter_GIRQ1;
> + int intr_counter_GIRQ0;
> + int intr_counter_CodRepIRQ;
> + int intr_counter_JPEGRepIRQ;
> + int field_counter;
> + int IRQ1_in;
> + int IRQ1_out;
> + int JPEG_in;
> + int JPEG_out;
> + int JPEG_0;
> + int JPEG_1;
> + int END_event_missed;
> + int JPEG_missed;
> + int JPEG_error;
> + int num_errors;
> + int JPEG_max_missed;
> + int JPEG_min_missed;
> +
> + u32 last_isr;
> + unsigned long frame_num;
> +
> + wait_queue_head_t test_q;
> +};
> +
> +#endif
> +
> +/*The following should be done in more portable way. It depends on define
> + of _ALPHA_BUZ in the Makefile.*/
> +
> +#ifdef _ALPHA_BUZ
> +#define btwrite(dat,adr) writel((dat),(char *) (zr->zr36057_adr+(adr)))
> +#define btread(adr) readl(zr->zr36057_adr+(adr))
> +#else
> +#define btwrite(dat,adr) writel((dat), (char *) (zr->zr36057_mem+(adr)))
> +#define btread(adr) readl(zr->zr36057_mem+(adr))
> +#endif
> +
> +#define btand(dat,adr) btwrite((dat) & btread(adr), adr)
> +#define btor(dat,adr) btwrite((dat) | btread(adr), adr)
> +#define btaor(dat,mask,adr) btwrite((dat) | ((mask) & btread(adr)), adr)
> +
> +#define I2C_TSA5522 0xc2
> +#define I2C_TDA9850 0xb6
> +#define I2C_HAUPEE 0xa0
> +#define I2C_STBEE 0xae
> +#define I2C_SAA7111 0x48
> +#define I2C_SAA7110 0x9c
> +#define I2C_SAA7185 0x88
> +//#define I2C_ADV7175 0xd4
> +#define I2C_ADV7175 0x54
> +
> +#define TDA9850_CON1 0x04
> +#define TDA9850_CON2 0x05
> +#define TDA9850_CON3 0x06
> +#define TDA9850_CON4 0x07
> +#define TDA9850_ALI1 0x08
> +#define TDA9850_ALI2 0x09
> +#define TDA9850_ALI3 0x0a
> +
> +#endif
More information about the MPlayer-dev-eng
mailing list