diff --git a/DOCS/man/en/mplayer.1 b/DOCS/man/en/mplayer.1 index cea1eb36af..6d4c1471c0 100644 --- a/DOCS/man/en/mplayer.1 +++ b/DOCS/man/en/mplayer.1 @@ -3270,68 +3270,6 @@ currently. Supported by at least the direct3d, gl, gl2, x11, xv and corevideo video output drivers. . -.TP -.B \-zrbw (\-vo zr only) -Display in black and white. -For optimal performance, this can be combined with '\-lavdopts gray'. -. -.TP -.B \-zrcrop <[width]x[height]+[x offset]+[y offset]> (\-vo zr only) -Select a part of the input image to display, multiple occurrences -of this option switch on cinerama mode. -In cinerama mode the movie is distributed over more than one TV -(or beamer) to create a larger image. -Options appearing after the n-th \-zrcrop apply to the n-th MJPEG card, each -card should at least have a \-zrdev in addition to the \-zrcrop. -For examples, see the output of \-zrhelp and the Zr section of the -documentation. -. -.TP -.B \-zrdev (\-vo zr only) -Specify the device special file that belongs to your MJPEG card, by default -the zr video output driver takes the first v4l device it can find. -. -.TP -.B \-zrfd (\-vo zr only) -Force decimation: Decimation, as specified by \-zrhdec and \-zrvdec, only -happens if the hardware scaler can stretch the image to its original size. -Use this option to force decimation. -. -.TP -.B \-zrhdec <1|2|4> (\-vo zr only) -Horizontal decimation: Ask the driver to send only every 2nd or 4th -line/\:pixel of the input image to the MJPEG card and use the scaler -of the MJPEG card to stretch the image to its original size. -. -.TP -.B \-zrhelp (\-vo zr only) -Display a list of all \-zr* options, their default values and a -cinerama mode example. -. -.TP -.B \-zrnorm (\-vo zr only) -Specify the TV norm as PAL or NTSC (default: no change). -. -.TP -.B \-zrquality <1\-20> (\-vo zr only) -A number from 1 (best) to 20 (worst) representing the JPEG encoding quality. -. -.TP -.B \-zrvdec <1|2|4> (\-vo zr only) -Vertical decimation: Ask the driver to send only every 2nd or 4th -line/\:pixel of the input image to the MJPEG card and use the scaler -of the MJPEG card to stretch the image to its original size. -. -.TP -.B \-zrxdoff (\-vo zr only) -If the movie is smaller than the TV screen, this option specifies the x -offset from the upper-left corner of the TV screen (default: centered). -. -.TP -.B \-zrydoff (\-vo zr only) -If the movie is smaller than the TV screen, this option specifies the y -offset from the upper-left corner of the TV screen (default: centered). -. . . .SH "VIDEO OUTPUT DRIVERS" @@ -4219,25 +4157,6 @@ output filename (default: ./grab.mpg) .PD 1 . .TP -.B zr (also see \-zr* and \-zrhelp) -Video output driver for a number of MJPEG capture/\:playback cards. -. -.TP -.B zr2 (also see the zrmjpeg video filter) -Video output driver for a number of MJPEG capture/\:playback cards, -second generation. -.PD 0 -.RSs -.IPs dev= -Specifies the video device to use. -.IPs norm= -Specifies the video norm to use (default: auto). -.IPs (no)prebuf -(De)Activate prebuffering, not yet supported. -.RE -.PD 1 -. -.TP .B "md5sum\ " Calculate MD5 sums of each frame and write them to a file. Supports RGB24 and YV12 colorspaces. @@ -7261,35 +7180,6 @@ algorithm to remove the logo. .RE . .TP -.B zrmjpeg[=options] -Software YV12 to MJPEG encoder for use with the zr2 video -output device. -.RSs -.IPs maxheight=|maxwidth= -These options set the maximum width and height the zr card -can handle (the MPlayer filter layer currently cannot query those). -.IPs {dc10+,dc10,buz,lml33}-{PAL|NTSC} -Use these options to set maxwidth and maxheight automatically to the -values known for card/\:mode combo. -For example, valid options are: dc10-PAL and buz-NTSC (default: dc10+PAL) -.IPs color|bw -Select color or black and white encoding. -Black and white encoding is faster. -Color is the default. -.IPs hdec={1,2,4} -Horizontal decimation 1, 2 or 4. -.IPs vdec={1,2,4} -Vertical decimation 1, 2 or 4. -.IPs quality=1\-20 -Set JPEG compression quality [BEST] 1 \- 20 [VERY BAD]. -.IPs fd|nofd -By default, decimation is only performed if the Zoran hardware -can upscale the resulting MJPEG images to the original size. -The option fd instructs the filter to always perform the requested -decimation (ugly). -.RE -. -.TP .B screenshot Allows acquiring screenshots of the movie using slave mode commands that can be bound to keypresses. @@ -7861,18 +7751,6 @@ mplayer tv:// \-tv driver=v4l:width=640:height=480:outfmt=i420 \-vc rawi420 \-vo .fi . .PP -.B Playback on Zoran cards (old style, deprecated): -.nf -mplayer \-vo zr \-vf scale=352:288 file.avi -.fi -. -.PP -.B Playback on Zoran cards (new style): -.nf -mplayer \-vo zr2 \-vf scale=352:288,zrmjpeg file.avi -.fi -. -.PP .B Play DTS-CD with passthrough: .nf mplayer \-ac hwdts \-rawaudio format=0x2001 \-cdrom\-device /dev/cdrom cdda:// diff --git a/Makefile b/Makefile index 49e8caf474..18d86fd87f 100644 --- a/Makefile +++ b/Makefile @@ -280,8 +280,6 @@ SRCS_COMMON-$(WIN32DLL) += libmpcodecs/ad_acm.c \ SRCS_COMMON-$(XANIM_CODECS) += libmpcodecs/vd_xanim.c SRCS_COMMON-$(XMMS_PLUGINS) += libmpdemux/demux_xmms.c SRCS_COMMON-$(XVID4) += libmpcodecs/vd_xvid4.c -SRCS_COMMON-$(ZR) += libmpcodecs/vd_zrmjpeg.c \ - libmpcodecs/vf_zrmjpeg.c SRCS_COMMON = asxparser.c \ av_log.c \ bstr.c \ @@ -562,7 +560,6 @@ SRCS_MPLAYER-$(XV) += libvo/vo_xv.c SRCS_MPLAYER-$(XVMC) += libvo/vo_xvmc.c SRCS_MPLAYER-$(XVR100) += libvo/vo_xvr100.c SRCS_MPLAYER-$(YUV4MPEG) += libvo/vo_yuv4mpeg.c -SRCS_MPLAYER-$(ZR) += libvo/jpeg_enc.c libvo/vo_zr.c libvo/vo_zr2.c SRCS_MPLAYER = command.c \ m_property.c \ diff --git a/cfg-mplayer.h b/cfg-mplayer.h index 084e73880b..e65890b35b 100644 --- a/cfg-mplayer.h +++ b/cfg-mplayer.h @@ -26,7 +26,6 @@ #include #include "cfg-common.h" -#include "libvo/vo_zr.h" #include "options.h" extern char *fb_mode_cfgfile; @@ -216,11 +215,6 @@ const m_option_t mplayer_opts[]={ {"aa*", "-aa* has been removed. Use -vo aa:suboption instead.\n", CONF_TYPE_PRINT, 0, 0, 0, NULL}, #endif -#ifdef CONFIG_ZR - // -vo zr - {"zr*", vo_zr_parseoption, CONF_TYPE_FUNC_FULL, 0, 0, 0, &vo_zr_revertoption }, -#endif - //---------------------- mplayer-only options ------------------------ diff --git a/codec-cfg.c b/codec-cfg.c index 84402ada7b..a7d958ebc1 100644 --- a/codec-cfg.c +++ b/codec-cfg.c @@ -212,9 +212,6 @@ static const struct { {"BGR1", IMGFMT_BGR1}, {"MPES", IMGFMT_MPEGPES}, - {"ZRMJPEGNI", IMGFMT_ZRMJPEGNI}, - {"ZRMJPEGIT", IMGFMT_ZRMJPEGIT}, - {"ZRMJPEGIB", IMGFMT_ZRMJPEGIB}, {"IDCT_MPEG2",IMGFMT_XVMC_IDCT_MPEG2}, {"MOCO_MPEG2",IMGFMT_XVMC_MOCO_MPEG2}, @@ -296,74 +293,6 @@ err_out_parse_error: return 0; } -#if 0 -static short get_driver(char *s,int audioflag) -{ - static char *audiodrv[] = { - "null", - "mp3lib", - "pcm", - "libac3", - "acm", - "alaw", - "msgsm", - "dshow", - "dvdpcm", - "hwac3", - "libvorbis", - "ffmpeg", - "libmad", - "msadpcm", - "liba52", - "g72x", - "imaadpcm", - "dk4adpcm", - "dk3adpcm", - "roqaudio", - "faad", - "realaud", - "libdv", - NULL - }; - static char *videodrv[] = { - "null", - "libmpeg2", - "vfw", - "dshow", - "ffmpeg", - "vfwex", - "raw", - "msrle", - "xanim", - "msvidc", - "fli", - "cinepak", - "qtrle", - "nuv", - "cyuv", - "qtsmc", - "ducktm1", - "roqvideo", - "qtrpza", - "mpng", - "ijpg", - "zlib", - "mpegpes", - "zrmjpeg", - "realvid", - "xvid", - "libdv", - NULL - }; - char **drv=audioflag?audiodrv:videodrv; - int i; - - for(i=0;drv[i];i++) if(!strcmp(s,drv[i])) return i; - - return -1; -} -#endif - static int validate_codec(codecs_t *c, int type) { unsigned int i; diff --git a/configure b/configure index 0e8e249a0b..f5ca0ee846 100755 --- a/configure +++ b/configure @@ -420,7 +420,6 @@ Video output: --enable-s3fb enable s3fb (S3 ViRGE) video output [disable] --enable-wii enable Nintendo Wii/GameCube video output [disable] --enable-directfb enable DirectFB video output [autodetect] - --enable-zr enable ZR360[56]7/ZR36060 video output [autodetect] --enable-bl enable Blinkenlights video output [disable] --enable-tdfxvid enable tdfx_vid video output [disable] --enable-xvr100 enable SUN XVR-100 video output [autodetect] @@ -685,7 +684,6 @@ _tdfxvid=no _xvr100=auto _tga=yes _directfb=auto -_zr=auto _bl=no _largefiles=yes #language=en @@ -1110,8 +1108,6 @@ for ac_option do --enable-tga) _tga=yes ;; --enable-directfb) _directfb=yes ;; --disable-directfb) _directfb=no ;; - --enable-zr) _zr=yes ;; - --disable-zr) _zr=no ;; --enable-bl) _bl=yes ;; --disable-bl) _bl=no ;; --enable-mtrr) _mtrr=yes ;; @@ -6293,31 +6289,6 @@ else fi echores "$_xmga" -echocheck "zr" -if test "$_zr" = auto ; then - #36067's seem to identify themselves as 36057PQC's, so the line - #below should work for 36067's and 36057's. - if grep -q -s -e "Multimedia video controller: Zoran Corporation ZR36057" /proc/pci ; then - _zr=yes - else - _zr=no - fi -fi -if test "$_zr" = yes ; then - if test "$ffmpeg_internals" = yes ; then - def_zr='#define CONFIG_ZR 1' - vomodules="zr zr2 $vomodules" - else - res_comment="FFmpeg internal headers are required by zr, sorry" - novomodules="zr $novomodules" - def_zr='#undef CONFIG_ZR' - fi -else - def_zr='#undef CONFIG_ZR' - novomodules="zr zr2 $novomodules" -fi -echores "$_zr" - echocheck "UnRAR executable" if test "$_unrar_exec" = auto ; then @@ -7036,7 +7007,6 @@ XVID4 = $_xvid XVMC = $_xvmc XVR100 = $_xvr100 YUV4MPEG = $_yuv4mpeg -ZR = $_zr # FFmpeg FFMPEG = $ffmpeg @@ -7405,7 +7375,6 @@ $def_xv $def_xvmc $def_xvr100 $def_yuv4mpeg -$def_zr /* FFmpeg */ diff --git a/etc/codecs.conf b/etc/codecs.conf index d353bb5716..f80d717043 100644 --- a/etc/codecs.conf +++ b/etc/codecs.conf @@ -1367,13 +1367,6 @@ videocodec geomp4 ; ijpg only decodes JPEG images (no MJPEG), and slow. ; Update: ffmjpeg is almost perfect (and optimized) now, prefer it to others. -videocodec zrmjpeg - info "Zoran MJPEG passthrough" - status buggy - fourcc MJPG,jpeg - driver zrmjpeg - out ZRMJPEGNI,ZRMJPEGIT,ZRMJPEGIB query - videocodec ffmjpeg info "FFmpeg MJPEG" status working diff --git a/libmpcodecs/vd.c b/libmpcodecs/vd.c index c7c0b58759..cbe979a100 100644 --- a/libmpcodecs/vd.c +++ b/libmpcodecs/vd.c @@ -52,7 +52,6 @@ extern const vd_functions_t mpcodecs_vd_mtga; extern const vd_functions_t mpcodecs_vd_sgi; extern const vd_functions_t mpcodecs_vd_libmpeg2; extern const vd_functions_t mpcodecs_vd_mpegpes; -extern const vd_functions_t mpcodecs_vd_zrmjpeg; extern const vd_functions_t mpcodecs_vd_realvid; extern const vd_functions_t mpcodecs_vd_xvid; extern const vd_functions_t mpcodecs_vd_libdv; @@ -95,9 +94,6 @@ const vd_functions_t * const mpcodecs_vd_drivers[] = { &mpcodecs_vd_libmpeg2, #endif &mpcodecs_vd_mpegpes, -#ifdef CONFIG_ZR - &mpcodecs_vd_zrmjpeg, -#endif #ifdef CONFIG_REALCODECS &mpcodecs_vd_realvid, #endif diff --git a/libmpcodecs/vd_zrmjpeg.c b/libmpcodecs/vd_zrmjpeg.c deleted file mode 100644 index 8dd460ab5b..0000000000 --- a/libmpcodecs/vd_zrmjpeg.c +++ /dev/null @@ -1,249 +0,0 @@ -/* - * Copyright (C) 2005 Rik Snel - * - based on vd_mpegpes.c by A'rpi (C) 2002-2003 - * - guess_mjpeg_type code stolen from lav_io.c (C) 2000 Rainer Johanni - * from the mjpegtools package - * - * 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. - */ - -#include -#include - -#include "config.h" -#include "mp_msg.h" -#include "vfcap.h" - -/* some convenient #define's, is this portable enough? */ -#define VERBOSE(...) mp_msg(MSGT_DECVIDEO, MSGL_V, "vd_zrmjpeg: " __VA_ARGS__) -#define ERROR(...) mp_msg(MSGT_DECVIDEO, MSGL_ERR, "vd_zrmjpeg: " __VA_ARGS__) -#define WARNING(...) mp_msg(MSGT_DECVIDEO, MSGL_WARN, \ - "vd_zrmjpeg: " __VA_ARGS__) - -#include "vd_internal.h" - -static const vd_info_t info = -{ - "Zoran MJPEG Video passthrough", - "zrmjpeg", - "Rik Snel ", - "Rik Snel ", - "for hw decoders (DC10(+)/buz/lml33)" -}; - -LIBVD_EXTERN(zrmjpeg) - -#include "libvo/video_out.h" - -typedef struct { - int vo_initialized; - unsigned int preferred_csp; -} vd_zrmjpeg_ctx_t; - -static int query_format(sh_video_t *sh, unsigned int format) { - vd_zrmjpeg_ctx_t *ctx = sh->context; - if (format == ctx->preferred_csp) return VFCAP_CSP_SUPPORTED; - return CONTROL_FALSE; -} - -// to set/get/query special features/parameters -static int control(sh_video_t *sh, int cmd, void* arg, ...) { - switch (cmd) { - case VDCTRL_QUERY_FORMAT: - return query_format(sh, *((unsigned int*)arg)); - } - return CONTROL_UNKNOWN; -} - -// init driver -static int init(sh_video_t *sh) { - vd_zrmjpeg_ctx_t *ctx; - - VERBOSE("init called\n"); - ctx = malloc(sizeof(*ctx)); - if (!ctx) return 0; - memset(ctx, 0, sizeof(*ctx)); - sh->context = ctx; - - /* defer init of vo until the first frame is known */ - return 1; -#if 0 - return mpcodecs_config_vo(sh, sh->disp_w, sh->disp_h, IMGFMT_ZRMJPEGIT); -#endif -} - -// uninit driver -static void uninit(sh_video_t *sh) { - free(sh->context); -} - -/* parts directly stolen from scan_jpg() and lav_open_input_file */ -static int get_int2(unsigned char *buf) { - return buf[0]*256 + buf[1]; -} - -#define M_SOF0 0xC0 -#define M_SOF1 0xC1 -#define M_DHT 0xC4 -#define M_SOI 0xD8 /* Start Of Image (beginning of datastream) */ -#define M_EOI 0xD9 /* End Of Image (end of datastream) */ -#define M_SOS 0xDA /* Start Of Scan (begins compressed data) */ -#define M_DQT 0xDB -#define M_APP0 0xE0 -#define M_APP1 0xE1 -/* returns 0 in case of failure */ -static unsigned int guess_mjpeg_type(unsigned char *data, unsigned int size, - int d_height) { - unsigned int p; - int marker, length, height, i, hf[3], vf[3]; - unsigned int app0 = 0, header = 0; - - /* The initial marker must be SIO */ - if (size < 2) { - ERROR("JPEG data too short (%d bytes)\n", size); - return 0; - } - - if (data[0] != 0xFF || data[1] != M_SOI) { - ERROR("JPEG data must start with FFD8, but doesn't\n"); - return 0; - } - - p = 2; /* pointer within jpeg data */ - - while (p < size) { - /* search 0xFF */ - while(data[p] != 0xFF) { - p++; - if (p >= size) return 0; - } - - /* get marker code, skip duplicate FF's */ - while(data[p] == 0xFF) { - p++; - if (p >= size) return 0; - } - - marker = data[p++]; - - /* marker may have an associated length */ - if (p <= size - 2) length = get_int2(data+p); - else length = 0; - - switch (marker) { - case M_SOF0: - case M_SOF1: - header = p-2; - VERBOSE("found offset of header %u\n", - header); - break; - case M_SOS: - size = 0; - continue; - case M_APP0: - app0 = p-2; - VERBOSE("found offset of APP0 %u\n", - app0); - break; - } - - /* these markers shouldn't have parameters, - * i.e. we don't need to skip anaything */ - if (marker == 0 || marker == 1 || - (marker >= 0xd0 && marker < 0xd8)) - continue; - - if (p + length <= size) p += length; - else { - ERROR("input JPEG too short, data missing\n"); - return 0; - } - } - - if (!header) { - ERROR("JPEG header (with resolution and sampling factors) not found\n"); - return 0; - } - - if (data[header + 9] != 3) { - ERROR("JPEG has wrong number of components\n"); - return 0; - } - - /* get the horizontal and vertical sample factors */ - for (i = 0; i < 3; i++) { - hf[i] = data[header + 10 + 3*i + 1]>>4; - vf[i] = data[header + 10 + 3*i + 1]&0x0F; - } - - if (hf[0] != 2 || hf[1] != 1 || hf[2] != 1 || - vf[0] != 1 || vf[1] != 1 || vf[2] != 1) { - ERROR("JPEG has wrong internal image format\n"); - } else VERBOSE("JPEG has colorspace YUV422 with minimal sampling factors (good)\n"); - - height = get_int2(data + header + 5); - if (height == d_height) { - VERBOSE("data is non interlaced\n"); - return IMGFMT_ZRMJPEGNI; - } - - if (2*height != d_height) { - ERROR("something very inconsistent happened\n"); - return 0; - } - - - if (app0 && get_int2(data + app0 + 2) >= 5 && - strncasecmp((char*)(data + app0 + 4), "AVI1", 4) == 0) { - if (data[app0+8] == 1) { - VERBOSE("data is interlaced, APP0: top-first (1)\n"); - return IMGFMT_ZRMJPEGIT; - } else { - VERBOSE("data is interlaced, APP0: bottom-first (%d)\n", - data[app0+8]); - return IMGFMT_ZRMJPEGIB; - } - } else { - VERBOSE("data is interlaced, no (valid) APP0 marker, " - "guessing top-first\n"); - return IMGFMT_ZRMJPEGIT; - } - - - return 0; -} - -// decode a frame -static mp_image_t* decode(sh_video_t *sh, void* data, int len, int flags) { - mp_image_t* mpi; - vd_zrmjpeg_ctx_t *ctx = sh->context; - - if (!ctx->vo_initialized) { - ctx->preferred_csp = guess_mjpeg_type(data, len, sh->disp_h); - if (ctx->preferred_csp == 0) return NULL; - mpcodecs_config_vo(sh, sh->disp_w, sh->disp_h, - ctx->preferred_csp); - ctx->vo_initialized = 1; - } - - mpi = mpcodecs_get_image(sh, MP_IMGTYPE_EXPORT, 0, - sh->disp_w, sh->disp_h); - /* abuse of mpi */ - mpi->planes[0]=(uint8_t*)data; - mpi->planes[1]=(uint8_t*)len; - return mpi; -} diff --git a/libmpcodecs/vf.c b/libmpcodecs/vf.c index bd4a63fb46..6355076726 100644 --- a/libmpcodecs/vf.c +++ b/libmpcodecs/vf.c @@ -55,7 +55,6 @@ extern const vf_info_t vf_info_rotate; extern const vf_info_t vf_info_mirror; extern const vf_info_t vf_info_palette; extern const vf_info_t vf_info_lavc; -extern const vf_info_t vf_info_zrmjpeg; extern const vf_info_t vf_info_dvbscale; extern const vf_info_t vf_info_cropdetect; extern const vf_info_t vf_info_test; @@ -143,9 +142,6 @@ static const vf_info_t* const filter_list[]={ &vf_info_lavcdeint, &vf_info_screenshot, &vf_info_uspp, -#endif -#ifdef CONFIG_ZR - &vf_info_zrmjpeg, #endif &vf_info_dvbscale, &vf_info_cropdetect, diff --git a/libmpcodecs/vf_zrmjpeg.c b/libmpcodecs/vf_zrmjpeg.c deleted file mode 100644 index 7d504ad290..0000000000 --- a/libmpcodecs/vf_zrmjpeg.c +++ /dev/null @@ -1,1049 +0,0 @@ -/* - * This files includes a straightforward (to be) optimized JPEG encoder for - * the YUV422 format, based on mjpeg code from ffmpeg. - * - * For an excellent introduction to the JPEG format, see: - * http://www.ece.purdue.edu/~bouman/grad-labs/lab8/pdf/lab.pdf - * - * Copyright (C) 2005 Rik Snel - * - based on vd_lavc.c by A'rpi (C) 2002-2003 - * - parts from ffmpeg Copyright (c) 2000-2003 Fabrice Bellard - * - * 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. - */ - -/** - * \file vf_zrmjpeg.c - * - * \brief Does mjpeg encoding as required by the zrmjpeg filter as well - * as by the zr video driver. - */ - -#include -#include -#include -#include - -#include "config.h" -#include "mp_msg.h" - -#include "img_format.h" -#include "mp_image.h" -#include "vd_ffmpeg.h" -#include "vf.h" - -/* We need this #define because we need ../libavcodec/common.h to #define - * be2me_32, otherwise the linker will complain that it doesn't exist */ -#define HAVE_AV_CONFIG_H -#include "libavcodec/avcodec.h" -#include "libavcodec/mjpegenc.h" - -#undef malloc -#undef free - -/* some convenient #define's, is this portable enough? */ -/// Printout with vf_zrmjpeg: prefix at VERBOSE level -#define VERBOSE(...) mp_msg(MSGT_DECVIDEO, MSGL_V, "vf_zrmjpeg: " __VA_ARGS__) -/// Printout with vf_zrmjpeg: prefix at ERROR level -#define ERROR(...) mp_msg(MSGT_DECVIDEO, MSGL_ERR, "vf_zrmjpeg: " __VA_ARGS__) -/// Printout with vf_zrmjpeg: prefix at WARNING level -#define WARNING(...) mp_msg(MSGT_DECVIDEO, MSGL_WARN, \ - "vf_zrmjpeg: " __VA_ARGS__) - -/// The get_pixels() routine to use. The real routine comes from dsputil -static void (*get_pixels)(DCTELEM *restrict block, const uint8_t *pixels, int line_size); - -/* Begin excessive code duplication ************************************/ -/* Code coming from mpegvideo.c and mjpeg.c in ../libavcodec ***********/ - -/// copy of the table in mpegvideo.c -static const unsigned short aanscales[64] = { - /**< precomputed values scaled up by 14 bits */ - 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, - 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, - 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, - 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, - 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, - 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, - 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446, - 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247 -}; - -/// Precompute DCT quantizing matrix -/** - * This routine will precompute the combined DCT matrix with qscale - * and DCT renorm needed by the MPEG encoder here. It is basically the - * same as the routine with the same name in mpegvideo.c, except for - * some coefficient changes. The matrix will be computed in two variations, - * depending on the DCT version used. The second used by the MMX version of DCT. - * - * \param s MpegEncContext pointer - * \param qmat[OUT] pointer to where the matrix is stored - * \param qmat16[OUT] pointer to where matrix for MMX is stored. - * This matrix is not permutated - * and second 64 entries are bias - * \param quant_matrix[IN] the quantizion matrix to use - * \param bias bias for the quantizer - * \param qmin minimum qscale value to set up for - * \param qmax maximum qscale value to set up for - * - * Only rows between qmin and qmax will be populated in the matrix. - * In this MJPEG encoder, only the value 8 for qscale is used. - */ -static void convert_matrix(MpegEncContext *s, int (*qmat)[64], - uint16_t (*qmat16)[2][64], const uint16_t *quant_matrix, - int bias, int qmin, int qmax) { - int qscale; - - for(qscale = qmin; qscale <= qmax; qscale++) { - int i; - if (s->dsp.fdct == ff_jpeg_fdct_islow) { - for (i = 0; i < 64; i++) { - const int j = s->dsp.idct_permutation[i]; -/* 16 <= qscale * quant_matrix[i] <= 7905 - * 19952 <= aanscales[i] * qscale * quant_matrix[i] <= 249205026 - * (1<<36)/19952 >= (1<<36)/(aanscales[i] * qscale * quant_matrix[i]) - * >= (1<<36)/249205026 - * 3444240 >= (1<<36)/(aanscales[i] * qscale * quant_matrix[i]) >= 275 */ - qmat[qscale][i] = (int)((UINT64_C(1) << - (QMAT_SHIFT-3))/ - (qscale*quant_matrix[j])); - } - } else if (s->dsp.fdct == fdct_ifast) { - for (i = 0; i < 64; i++) { - const int j = s->dsp.idct_permutation[i]; -/* 16 <= qscale * quant_matrix[i] <= 7905 - * 19952 <= aanscales[i] * qscale * quant_matrix[i] <= 249205026 - * (1<<36)/19952 >= (1<<36)/(aanscales[i] * qscale * quant_matrix[i]) - * >= (1<<36)/249205026 - * 3444240 >= (1<<36)/(aanscales[i] * qscale * quant_matrix[i]) >= 275 */ - qmat[qscale][i] = (int)((UINT64_C(1) << - (QMAT_SHIFT + 11))/(aanscales[i] - *qscale * quant_matrix[j])); - } - } else { - for (i = 0; i < 64; i++) { - const int j = s->dsp.idct_permutation[i]; -/* We can safely assume that 16 <= quant_matrix[i] <= 255 - * So 16 <= qscale * quant_matrix[i] <= 7905 - * so (1<<19) / 16 >= (1<<19) / (qscale * quant_matrix[i]) >= (1<<19) / 7905 - * so 32768 >= (1<<19) / (qscale * quant_matrix[i]) >= 67 */ - qmat[qscale][i] = (int)((UINT64_C(1) << - QMAT_SHIFT_MMX) / (qscale - *quant_matrix[j])); - qmat16[qscale][0][i] = (1 << QMAT_SHIFT_MMX) - /(qscale * quant_matrix[j]); - - if (qmat16[qscale][0][i] == 0 || - qmat16[qscale][0][i] == 128*256) - qmat16[qscale][0][i]=128*256-1; - qmat16[qscale][1][i]=ROUNDED_DIV(bias - <<(16-QUANT_BIAS_SHIFT), - qmat16[qscale][0][i]); - } - } - } -} - -/// Emit the DC value into a MJPEG code sream -/** - * This routine is only intended to be used from encode_block - * - * \param s pointer to MpegEncContext structure - * \param val the DC value to emit - * \param huff_size pointer to huffman code size array - * \param huff_code pointer to the code array corresponding to \a huff_size - * - * This routine is a clone of mjpeg_encode_dc - */ -static inline void encode_dc(MpegEncContext *s, int val, - uint8_t *huff_size, uint16_t *huff_code) { - int mant, nbits; - - if (val == 0) { - put_bits(&s->pb, huff_size[0], huff_code[0]); - } else { - mant = val; - if (val < 0) { - val = -val; - mant--; - } - nbits= av_log2_16bit(val) + 1; - put_bits(&s->pb, huff_size[nbits], huff_code[nbits]); - put_bits(&s->pb, nbits, mant & ((1 << nbits) - 1)); - } -} - -/// Huffman encode and emit one DCT block into the MJPEG code stream -/** - * \param s pointer to MpegEncContext structure - * \param block pointer to the DCT block to emit - * \param n - * - * This routine is a duplicate of encode_block in mjpeg.c - */ -static void encode_block(MpegEncContext *s, DCTELEM *block, int n) { - int mant, nbits, code, i, j; - int component, dc, run, last_index, val; - MJpegContext *m = s->mjpeg_ctx; - uint8_t *huff_size_ac; - uint16_t *huff_code_ac; - - /* DC coef */ - component = (n <= 3 ? 0 : n - 4 + 1); - dc = block[0]; /* overflow is impossible */ - val = dc - s->last_dc[component]; - if (n < 4) { - encode_dc(s, val, m->huff_size_dc_luminance, - m->huff_code_dc_luminance); - huff_size_ac = m->huff_size_ac_luminance; - huff_code_ac = m->huff_code_ac_luminance; - } else { - encode_dc(s, val, m->huff_size_dc_chrominance, - m->huff_code_dc_chrominance); - huff_size_ac = m->huff_size_ac_chrominance; - huff_code_ac = m->huff_code_ac_chrominance; - } - s->last_dc[component] = dc; - - /* AC coefs */ - - run = 0; - last_index = s->block_last_index[n]; - for (i = 1; i <= last_index; i++) { - j = s->intra_scantable.permutated[i]; - val = block[j]; - if (val == 0) run++; - else { - while (run >= 16) { - put_bits(&s->pb, huff_size_ac[0xf0], - huff_code_ac[0xf0]); - run -= 16; - } - mant = val; - if (val < 0) { - val = -val; - mant--; - } - - nbits= av_log2_16bit(val) + 1; - code = (run << 4) | nbits; - - put_bits(&s->pb, huff_size_ac[code], - huff_code_ac[code]); - put_bits(&s->pb, nbits, mant & ((1 << nbits) - 1)); - run = 0; - } - } - - /* output EOB only if not already 64 values */ - if (last_index < 63 || run != 0) - put_bits(&s->pb, huff_size_ac[0], huff_code_ac[0]); -} - -/// clip overflowing DCT coefficients -/** - * If the computed DCT coefficients in a block overflow, this routine - * will go through them and clip them to be in the valid range. - * - * \param s pointer to MpegEncContext - * \param block pointer to DCT block to process - * \param last_index index of the last non-zero coefficient in block - * - * The max and min level, which are clipped to, are stored in - * s->min_qcoeff and s->max_qcoeff respectively. - */ -static inline void clip_coeffs(MpegEncContext *s, DCTELEM *block, - int last_index) { - int i; - const int maxlevel= s->max_qcoeff; - const int minlevel= s->min_qcoeff; - - for (i = 0; i <= last_index; i++) { - const int j = s->intra_scantable.permutated[i]; - int level = block[j]; - - if (level > maxlevel) level=maxlevel; - else if(level < minlevel) level=minlevel; - block[j]= level; - } -} - -/* End excessive code duplication **************************************/ - -typedef struct { - struct MpegEncContext *s; - int cheap_upsample; - int bw; - int y_rs; - int u_rs; - int v_rs; -} jpeg_enc_t; - -// Huffman encode and emit one MCU of MJPEG code -/** - * \param j pointer to jpeg_enc_t structure - * - * This function huffman encodes one MCU, and emits the - * resulting bitstream into the MJPEG code that is currently worked on. - * - * this function is a reproduction of the one in mjpeg, it includes two - * changes, it allows for black&white encoding (it skips the U and V - * macroblocks and it outputs the huffman code for 'no change' (dc) and - * 'all zero' (ac)) and it takes 4 macroblocks (422) instead of 6 (420) - */ -static av_always_inline void zr_mjpeg_encode_mb(jpeg_enc_t *j) { - - MJpegContext *m = j->s->mjpeg_ctx; - - encode_block(j->s, j->s->block[0], 0); - encode_block(j->s, j->s->block[1], 1); - if (j->bw) { - /* U */ - put_bits(&j->s->pb, m->huff_size_dc_chrominance[0], - m->huff_code_dc_chrominance[0]); - put_bits(&j->s->pb, m->huff_size_ac_chrominance[0], - m->huff_code_ac_chrominance[0]); - /* V */ - put_bits(&j->s->pb, m->huff_size_dc_chrominance[0], - m->huff_code_dc_chrominance[0]); - put_bits(&j->s->pb, m->huff_size_ac_chrominance[0], - m->huff_code_ac_chrominance[0]); - } else { - /* we trick encode_block here so that it uses - * chrominance huffman tables instead of luminance ones - * (see the effect of second argument of encode_block) */ - encode_block(j->s, j->s->block[2], 4); - encode_block(j->s, j->s->block[3], 5); - } -} - -/// Fill one DCT MCU from planar storage -/** - * This routine will convert one MCU from YUYV planar storage into 4 - * DCT macro blocks, converting from 8-bit format in the planar - * storage to 16-bit format used in the DCT. - * - * \param j pointer to jpeg_enc structure, and also storage for DCT macro blocks - * \param x pixel x-coordinate for the first pixel - * \param y pixel y-coordinate for the first pixel - * \param y_data pointer to the Y plane - * \param u_data pointer to the U plane - * \param v_data pointer to the V plane - */ -static av_always_inline void fill_block(jpeg_enc_t *j, int x, int y, - unsigned char *y_data, unsigned char *u_data, - unsigned char *v_data) -{ - int i, k; - short int *dest; - unsigned char *source; - - // The first Y, Y0 - get_pixels(j->s->block[0], y*8*j->y_rs + 16*x + y_data, j->y_rs); - // The second Y, Y1 - get_pixels(j->s->block[1], y*8*j->y_rs + 16*x + 8 + y_data, j->y_rs); - - if (!j->bw && j->cheap_upsample) { - source = y * 4 * j->u_rs + 8*x + u_data; - dest = j->s->block[2]; - for (i = 0; i < 4; i++) { - for (k = 0; k < 8; k++) { - dest[k] = source[k]; // First row - dest[k+8] = source[k]; // Duplicate to next row - - } - dest += 16; - source += j->u_rs; - } - source = y * 4 * j->v_rs + 8*x + v_data; - dest = j->s->block[3]; - for (i = 0; i < 4; i++) { - for (k = 0; k < 8; k++) { - dest[k] = source[k]; - dest[k+8] = source[k]; - } - dest += 16; - source += j->u_rs; - } - } else if (!j->bw && !j->cheap_upsample) { - // U - get_pixels(j->s->block[2], y*8*j->u_rs + 8*x + u_data, j->u_rs); - // V - get_pixels(j->s->block[3], y*8*j->v_rs + 8*x + v_data, j->v_rs); - } -} - -/** - * \brief initialize mjpeg encoder - * - * This routine is to set up the parameters and initialize the mjpeg encoder. - * It does all the initializations needed of lower level routines. - * The formats accepted by this encoder is YUV422P and YUV420 - * - * \param w width in pixels of the image to encode, must be a multiple of 16 - * \param h height in pixels of the image to encode, must be a multiple of 8 - * \param y_rsize size of each plane row Y component - * \param y_rsize size of each plane row U component - * \param v_rsize size of each plane row V component - * \param cu "cheap upsample". Set to 0 for YUV422 format, 1 for YUV420 format - * when set to 1, the encoder will assume that there is only half th - * number of rows of chroma information, and every chroma row is - * duplicated. - * \param q quality parameter for the mjpeg encode. Between 1 and 20 where 1 - * is best quality and 20 is the worst quality. - * \param b monochrome flag. When set to 1, the mjpeg output is monochrome. - * In that case, the colour information is omitted, and actually the - * colour planes are not touched. - * - * \returns an appropriately set up jpeg_enc_t structure - * - * The actual plane buffer addreses are passed by jpeg_enc_frame(). - * - * The encoder doesn't know anything about interlacing, the halve height - * needs to be passed and the double rowstride. Which field gets encoded - * is decided by what buffers are passed to mjpeg_encode_frame() - */ -static jpeg_enc_t *jpeg_enc_init(int w, int h, int y_rsize, - int u_rsize, int v_rsize, - int cu, int q, int b) { - jpeg_enc_t *j; - int i = 0; - VERBOSE("JPEG encoder init: %dx%d %d %d %d cu=%d q=%d bw=%d\n", - w, h, y_rsize, u_rsize, v_rsize, cu, q, b); - - j = av_mallocz(sizeof(jpeg_enc_t)); - if (j == NULL) return NULL; - - j->s = av_mallocz(sizeof(MpegEncContext)); - if (j->s == NULL) { - av_free(j); - return NULL; - } - - /* info on how to access the pixels */ - j->y_rs = y_rsize; - j->u_rs = u_rsize; - j->v_rs = v_rsize; - - j->s->width = w; // image width and height - j->s->height = h; - j->s->qscale = q; // Encoding quality - - j->s->out_format = FMT_MJPEG; - j->s->intra_only = 1; // Generate only intra pictures for jpeg - j->s->encoding = 1; // Set mode to encode - j->s->pict_type = FF_I_TYPE; - j->s->y_dc_scale = 8; - j->s->c_dc_scale = 8; - - /* - * This sets up the MCU (Minimal Code Unit) number - * of appearances of the various component - * for the SOF0 table in the generated MJPEG. - * The values are not used for anything else. - * The current setup is simply YUV422, with two horizontal Y components - * for every UV component. - */ - //FIXME j->s->mjpeg_write_tables = 1; // setup to write tables - j->s->mjpeg_vsample[0] = 1; // 1 appearance of Y vertically - j->s->mjpeg_vsample[1] = 1; // 1 appearance of U vertically - j->s->mjpeg_vsample[2] = 1; // 1 appearance of V vertically - j->s->mjpeg_hsample[0] = 2; // 2 appearances of Y horizontally - j->s->mjpeg_hsample[1] = 1; // 1 appearance of U horizontally - j->s->mjpeg_hsample[2] = 1; // 1 appearance of V horizontally - - j->cheap_upsample = cu; - j->bw = b; - - init_avcodec(); - - // Build mjpeg huffman code tables, setting up j->s->mjpeg_ctx - if (ff_mjpeg_encode_init(j->s) < 0) { - av_free(j->s); - av_free(j); - return NULL; - } - - /* alloc bogus avctx to keep MPV_common_init from segfaulting */ - j->s->avctx = avcodec_alloc_context(); - if (j->s->avctx == NULL) { - av_free(j->s); - av_free(j); - return NULL; - } - - // Set some a minimum amount of default values that are needed - // Indicates that we should generated normal MJPEG - j->s->avctx->codec_id = CODEC_ID_MJPEG; - // Which DCT method to use. AUTO will select the fastest one - j->s->avctx->dct_algo = FF_DCT_AUTO; - j->s->intra_quant_bias= 1<<(QUANT_BIAS_SHIFT-1); //(a + x/2)/x - // indicate we 'decode' to jpeg 4:2:2 - j->s->avctx->pix_fmt = PIX_FMT_YUVJ422P; - - j->s->avctx->thread_count = 1; - - /* make MPV_common_init allocate important buffers, like s->block - * Also initializes dsputil */ - if (MPV_common_init(j->s) < 0) { - av_free(j->s); - av_free(j); - return NULL; - } - - /* correct the value for sc->mb_height. MPV_common_init put other - * values there */ - j->s->mb_height = j->s->height/8; - j->s->mb_intra = 1; - - // Init q matrix - j->s->intra_matrix[0] = ff_mpeg1_default_intra_matrix[0]; - for (i = 1; i < 64; i++) - j->s->intra_matrix[i] = av_clip_uint8( - (ff_mpeg1_default_intra_matrix[i]*j->s->qscale) >> 3); - - // precompute matrix - convert_matrix(j->s, j->s->q_intra_matrix, j->s->q_intra_matrix16, - j->s->intra_matrix, j->s->intra_quant_bias, 8, 8); - - /* Pick up the selection of the optimal get_pixels() routine - * to use, which was done in MPV_common_init() */ - get_pixels = j->s->dsp.get_pixels; - - return j; -} - -/** - * \brief mjpeg encode an image - * - * This routine will take a 3-plane YUV422 image and encoded it with MJPEG - * base line format, as suitable as input for the Zoran hardare MJPEG chips. - * - * It requires that the \a j parameter points the structure set up by the - * jpeg_enc_init() routine. - * - * \param j pointer to jpeg_enc_t structure as created by jpeg_enc_init() - * \param y_data pointer to Y component plane, packed one byte/pixel - * \param u_data pointer to U component plane, packed one byte per every - * other pixel - * \param v_data pointer to V component plane, packed one byte per every - * other pixel - * \param bufr pointer to the buffer where the mjpeg encoded code is stored - * - * \returns the number of bytes stored into \a bufr - * - * If \a j->s->mjpeg_write_tables is set, it will also emit the mjpeg tables, - * otherwise it will just emit the data. The \a j->s->mjpeg_write_tables - * variable will be reset to 0 by the routine. - */ -static int jpeg_enc_frame(jpeg_enc_t *j, uint8_t *y_data, - uint8_t *u_data, uint8_t *v_data, uint8_t *bufr) { - int mb_x, mb_y, overflow; - /* initialize the buffer */ - - init_put_bits(&j->s->pb, bufr, 1024*256); - - // Emit the mjpeg header blocks - ff_mjpeg_encode_picture_header(j->s); - - j->s->header_bits = put_bits_count(&j->s->pb); - - j->s->last_dc[0] = 128; - j->s->last_dc[1] = 128; - j->s->last_dc[2] = 128; - - for (mb_y = 0; mb_y < j->s->mb_height; mb_y++) { - for (mb_x = 0; mb_x < j->s->mb_width; mb_x++) { - /* - * Fill one DCT block (8x8 pixels) from - * 2 Y macroblocks and one U and one V - */ - fill_block(j, mb_x, mb_y, y_data, u_data, v_data); - emms_c(); /* is this really needed? */ - - j->s->block_last_index[0] = - j->s->dct_quantize(j->s, j->s->block[0], - 0, 8, &overflow); - if (overflow) clip_coeffs(j->s, j->s->block[0], - j->s->block_last_index[0]); - j->s->block_last_index[1] = - j->s->dct_quantize(j->s, j->s->block[1], - 1, 8, &overflow); - if (overflow) clip_coeffs(j->s, j->s->block[1], - j->s->block_last_index[1]); - - if (!j->bw) { - j->s->block_last_index[4] = - j->s->dct_quantize(j->s, j->s->block[2], - 4, 8, &overflow); - if (overflow) clip_coeffs(j->s, j->s->block[2], - j->s->block_last_index[2]); - j->s->block_last_index[5] = - j->s->dct_quantize(j->s, j->s->block[3], - 5, 8, &overflow); - if (overflow) clip_coeffs(j->s, j->s->block[3], - j->s->block_last_index[3]); - } - zr_mjpeg_encode_mb(j); - } - } - emms_c(); - ff_mjpeg_encode_picture_trailer(j->s); - flush_put_bits(&j->s->pb); - - //FIXME - //if (j->s->mjpeg_write_tables == 1) - // j->s->mjpeg_write_tables = 0; - - return put_bits_ptr(&(j->s->pb)) - j->s->pb.buf; -} - -/// the real uninit routine -/** - * This is the real routine that does the uninit of the ZRMJPEG filter - * - * \param j pointer to jpeg_enc structure - */ -static void jpeg_enc_uninit(jpeg_enc_t *j) { - ff_mjpeg_encode_close(j->s); - av_free(j->s); - av_free(j); -} - -/// Private structure for ZRMJPEG filter -struct vf_priv_s { - jpeg_enc_t *j; - unsigned char buf[256*1024]; - int bw, fd, hdec, vdec; - int fields; - int y_stride; - int c_stride; - int quality; - int maxwidth; - int maxheight; -}; - -/// vf CONFIGURE entry point for the ZRMJPEG filter -/** - * \param vf video filter instance pointer - * \param width image source width in pixels - * \param height image source height in pixels - * \param d_width width of requested window, just a hint - * \param d_height height of requested window, just a hint - * \param flags vf filter flags - * \param outfmt - * - * \returns returns 0 on error - * - * This routine will make the necessary hardware-related decisions for - * the ZRMJPEG filter, do the initialization of the MJPEG encoder, and - * then select one of the ZRJMJPEGIT or ZRMJPEGNI filters and then - * arrange to dispatch to the config() entry pointer for the one - * selected. - */ -static int config(struct vf_instance *vf, int width, int height, int d_width, - int d_height, unsigned int flags, unsigned int outfmt){ - struct vf_priv_s *priv = vf->priv; - float aspect_decision; - int stretchx, stretchy, err = 0, maxstretchx = 4; - priv->fields = 1; - - VERBOSE("config() called\n"); - - if (priv->j) { - VERBOSE("re-configuring, resetting JPEG encoder\n"); - jpeg_enc_uninit(priv->j); - priv->j = NULL; - } - - aspect_decision = ((float)d_width/(float)d_height)/ - ((float)width/(float)height); - - if (aspect_decision > 1.8 && aspect_decision < 2.2) { - VERBOSE("should correct aspect by stretching x times 2, %d %d\n", 2*width, priv->maxwidth); - if (2*width <= priv->maxwidth) { - d_width = 2*width; - d_height = height; - maxstretchx = 2; - } else { - WARNING("unable to correct aspect by stretching, because resulting X will be too large, aspect correction by decimating y not yet implemented\n"); - d_width = width; - d_height = height; - } - /* prestretch movie */ - } else { - /* uncorrecting output for now */ - d_width = width; - d_height = height; - } - /* 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 (d_width > priv->maxwidth/2 || height > priv->maxheight/2 - || maxstretchx == 1) { - stretchx = 1; - stretchy = 1; - priv->fields = 2; - if (priv->vdec == 2) { - priv->fields = 1; - } else if (priv->vdec == 4) { - priv->fields = 1; - stretchy = 2; - } - if (priv->hdec > maxstretchx) { - if (priv->fd) { - WARNING("horizontal decimation too high, " - "changing to %d (use fd to keep" - " hdec=%d)\n", - maxstretchx, priv->hdec); - priv->hdec = maxstretchx; - } - } - stretchx = priv->hdec; - } else if (d_width > priv->maxwidth/4 || - height > priv->maxheight/4 || - maxstretchx == 2) { - stretchx = 2; - stretchy = 1; - priv->fields = 1; - if (priv->vdec == 2) { - stretchy = 2; - } else if (priv->vdec == 4) { - if (!priv->fd) { - WARNING("vertical decimation too high, " - "changing to 2 (use fd to keep " - "vdec=4)\n"); - priv->vdec = 2; - } - stretchy = 2; - } - if (priv->hdec == 2) { - stretchx = 4; - } else if (priv->hdec == 4) { - if (priv->fd) { - WARNING("horizontal decimation too high, " - "changing to 2 (use fd to keep " - "hdec=4)\n"); - priv->hdec = 2; - } - stretchx = 4; - } - } else { - /* output image is maximally stretched */ - stretchx = 4; - stretchy = 2; - priv->fields = 1; - if (priv->vdec != 1 && !priv->fd) { - WARNING("vertical decimation too high, changing to 1 " - "(use fd to keep vdec=%d)\n", - priv->vdec); - priv->vdec = 1; - } - if (priv->hdec != 1 && !priv->fd) { - WARNING("horizontal decimation too high, changing to 1 (use fd to keep hdec=%d)\n", priv->hdec); - priv->hdec = 1; - } - } - - VERBOSE("generated JPEG's %dx%s%d%s, stretched to %dx%d\n", - width/priv->hdec, (priv->fields == 2) ? "(" : "", - height/(priv->vdec*priv->fields), - (priv->fields == 2) ? "x2)" : "", - (width/priv->hdec)*stretchx, - (height/(priv->vdec*priv->fields))* - stretchy*priv->fields); - - - if ((width/priv->hdec)*stretchx > priv->maxwidth || - (height/(priv->vdec*priv->fields))* - stretchy*priv->fields > priv->maxheight) { - ERROR("output dimensions too large (%dx%d), max (%dx%d) " - "insert crop to fix\n", - (width/priv->hdec)*stretchx, - (height/(priv->vdec*priv->fields))* - stretchy*priv->fields, - priv->maxwidth, priv->maxheight); - err = 1; - } - - if (width%(16*priv->hdec) != 0) { - ERROR("width must be a multiple of 16*hdec (%d), use expand\n", - priv->hdec*16); - err = 1; - } - - if (height%(8*priv->fields*priv->vdec) != 0) { - ERROR("height must be a multiple of 8*fields*vdec (%d)," - " use expand\n", priv->vdec*priv->fields*8); - err = 1; - } - - if (err) return 0; - - priv->y_stride = width; - priv->c_stride = width/2; - priv->j = jpeg_enc_init(width, height/priv->fields, - priv->fields*priv->y_stride, - priv->fields*priv->c_stride, - priv->fields*priv->c_stride, - 1, priv->quality, priv->bw); - - if (!priv->j) return 0; - return vf_next_config(vf, width, height, d_width, d_height, flags, - (priv->fields == 2) ? IMGFMT_ZRMJPEGIT : IMGFMT_ZRMJPEGNI); -} - -/// put_image entrypoint for the ZRMJPEG vf filter -/*** - * \param vf pointer to vf_instance - * \param mpi pointer to mp_image_t structure - * \param pts - */ -static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){ - struct vf_priv_s *priv = vf->priv; - int size = 0; - int i; - mp_image_t* dmpi; - for (i = 0; i < priv->fields; i++) - size += jpeg_enc_frame(priv->j, - mpi->planes[0] + i*priv->y_stride, - mpi->planes[1] + i*priv->c_stride, - mpi->planes[2] + i*priv->c_stride, - priv->buf + size); - - dmpi = vf_get_image(vf->next, IMGFMT_ZRMJPEGNI, - MP_IMGTYPE_EXPORT, 0, mpi->w, mpi->h); - dmpi->planes[0] = (uint8_t*)priv->buf; - dmpi->planes[1] = (uint8_t*)size; - return vf_next_put_image(vf,dmpi, pts); -} - -/// query_format entrypoint for the ZRMJPEG vf filter -/*** - * \param vf pointer to vf_instance - * \param fmt image format to query for - * - * \returns 0 if image format in fmt is not supported - * - * Given the image format specified by \a fmt, this routine is called - * to ask if the format is supported or not. - */ -static int query_format(struct vf_instance *vf, unsigned int fmt){ - VERBOSE("query_format() called\n"); - - switch (fmt) { - case IMGFMT_YV12: - case IMGFMT_YUY2: - /* strictly speaking the output format of - * this filter will be known after config(), - * but everything that supports IMGFMT_ZRMJPEGNI - * should also support all other IMGFMT_ZRMJPEG* */ - return vf_next_query_format(vf, IMGFMT_ZRMJPEGNI); - } - - return 0; -} - -/// vf UNINIT entry point for the ZRMJPEG filter -/** - * \param vf pointer to the vf instance structure - */ -static void uninit(vf_instance_t *vf) { - struct vf_priv_s *priv = vf->priv; - VERBOSE("uninit() called\n"); - if (priv->j) jpeg_enc_uninit(priv->j); - free(priv); -} - -/// vf OPEN entry point for the ZRMJPEG filter -/** - * \param vf pointer to the vf instance structure - * \param args the argument list string for the -vf zrmjpeg command - * - * \returns 0 for error, 1 for success - * - * This routine will do some basic initialization of local structures etc., - * and then parse the command line arguments specific for the ZRMJPEG filter. - */ -static int vf_open(vf_instance_t *vf, char *args){ - struct vf_priv_s *priv; - VERBOSE("vf_open() called: args=\"%s\"\n", args); - - vf->config = config; - vf->put_image = put_image; - vf->query_format = query_format; - vf->uninit = uninit; - - priv = vf->priv = calloc(sizeof(*priv), 1); - if (!vf->priv) { - ERROR("out of memory error\n"); - return 0; - } - - /* maximum displayable size by zoran card, these defaults - * are for my own zoran card in PAL mode, these can be changed - * by filter options. But... in an ideal world these values would - * be queried from the vo device itself... */ - priv->maxwidth = 768; - priv->maxheight = 576; - - priv->quality = 2; - priv->hdec = 1; - priv->vdec = 1; - - init_avcodec(); - - if (args) { - char *arg, *tmp, *ptr, junk; - int last = 0, input; - - /* save arguments, to be able to safely modify them */ - arg = strdup(args); - if (!arg) { - ERROR("out of memory, this is bad\n"); - return 0; - } - - tmp = ptr = arg; - do { - while (*tmp != ':' && *tmp) tmp++; - if (*tmp == ':') *tmp++ = '\0'; - else last = 1; - VERBOSE("processing filter option \"%s\"\n", ptr); - /* These options deal with the maximum output - * resolution of the zoran card. These should - * be queried from the vo device, but it is currently - * too difficult, so the user should tell the filter */ - if (!strncmp("maxheight=", ptr, 10)) { - if (sscanf(ptr+10, "%d%c", &input, &junk) != 1) - ERROR( - "error parsing parameter to \"maxheight=\", \"%s\", ignoring\n" - , ptr + 10); - else { - priv->maxheight = input; - VERBOSE("setting maxheight to %d\n", - priv->maxheight); - } - } else if (!strncmp("quality=", ptr, 8)) { - if (sscanf(ptr+8, "%d%c", &input, &junk) != 1) - ERROR( - "error parsing parameter to \"quality=\", \"%s\", ignoring\n" - , ptr + 8); - else if (input < 1 || input > 20) - ERROR( - "parameter to \"quality=\" out of range (1..20), %d\n", input); - else { - priv->quality = input; - VERBOSE("setting JPEG quality to %d\n", - priv->quality); - } - } else if (!strncmp("maxwidth=", ptr, 9)) { - if (sscanf(ptr+9, "%d%c", &input, &junk) != 1) - ERROR( - "error parsing parameter to \"maxwidth=\", \"%s\", ignoring\n" - , ptr + 9); - else { - priv->maxwidth = input; - VERBOSE("setting maxwidth to %d\n", - priv->maxwidth); - } - } else if (!strncmp("hdec=", ptr, 5)) { - if (sscanf(ptr+5, "%d%c", &input, &junk) != 1) - ERROR( - "error parsing parameter to \"hdec=\", \"%s\", ignoring\n" - , ptr + 9); - else if (input != 1 && input != 2 && input != 4) - ERROR( - "illegal parameter to \"hdec=\", %d, should be 1, 2 or 4", - input); - else { - priv->hdec = input; - VERBOSE( - "setting horizontal decimation to %d\n", priv->maxwidth); - } - } else if (!strncmp("vdec=", ptr, 5)) { - if (sscanf(ptr+5, "%d%c", &input, &junk) != 1) - ERROR( - "error parsing parameter to \"vdec=\", \"%s\", ignoring\n" - , ptr + 9); - else if (input != 1 && input != 2 && input != 4) - ERROR( - "illegal parameter to \"vdec=\", %d, should be 1, 2 or 4", - input); - else { - priv->vdec = input; - VERBOSE( - "setting vertical decimation to %d\n", priv->maxwidth); - } - } else if (!strcasecmp("dc10+-PAL", ptr) || - !strcasecmp("dc10-PAL", ptr)) { - priv->maxwidth = 768; - priv->maxheight = 576; - VERBOSE("setting DC10(+) PAL profile\n"); - } else if (!strcasecmp("fd", ptr)) { - priv->fd = 1; - VERBOSE("forcing decimation\n"); - } else if (!strcasecmp("nofd", ptr)) { - priv->fd = 0; - VERBOSE("decimate only if beautiful\n"); - } else if (!strcasecmp("bw", ptr)) { - priv->bw = 1; - VERBOSE("setting black and white encoding\n"); - } else if (!strcasecmp("color", ptr)) { - priv->bw = 0; - VERBOSE("setting color encoding\n"); - } else if (!strcasecmp("dc10+-NTSC", ptr) || - !strcasecmp("dc10-NTSC", ptr)) { - priv->maxwidth = 640; - priv->maxheight = 480; - VERBOSE("setting DC10(+) NTSC profile\n"); - } else if (!strcasecmp("buz-PAL", ptr) || - !strcasecmp("lml33-PAL", ptr)) { - priv->maxwidth = 720; - priv->maxheight = 576; - VERBOSE("setting buz/lml33 PAL profile\n"); - } else if (!strcasecmp("buz-NTSC", ptr) || - !strcasecmp("lml33-NTSC", ptr)) { - priv->maxwidth = 720; - priv->maxheight = 480; - VERBOSE("setting buz/lml33 NTSC profile\n"); - } else { - WARNING("ignoring unknown filter option " - "\"%s\", or missing argument\n", - ptr); - } - ptr = tmp; - } while (!last); - - free(arg); - } - - - return 1; -} - -const vf_info_t vf_info_zrmjpeg = { - "realtime zoran MJPEG encoding", - "zrmjpeg", - "Rik Snel", - "", - vf_open, - NULL -}; diff --git a/libvo/jpeg_enc.c b/libvo/jpeg_enc.c deleted file mode 100644 index 37b5010250..0000000000 --- a/libvo/jpeg_enc.c +++ /dev/null @@ -1,485 +0,0 @@ -/* - * straightforward (to be) optimized JPEG encoder for the YUV422 format - * based on MJPEG code from FFmpeg - * - * For an excellent introduction to the JPEG format, see: - * http://www.ece.purdue.edu/~bouman/grad-labs/lab8/pdf/lab.pdf - * - * Copyright (c) 2002, Rik Snel - * parts from FFmpeg Copyright (c) 2000-2002 Fabrice Bellard - * - * 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. - */ - - - -#include -#include -#include -#include -#include "config.h" -#include "mp_msg.h" -/* We need this #define because we need ../libavcodec/common.h to #define - * be2me_32, otherwise the linker will complain that it doesn't exist */ -#define HAVE_AV_CONFIG_H -#include "libavcodec/avcodec.h" -#include "libavcodec/dsputil.h" -#include "libavcodec/mpegvideo.h" -#include "libavcodec/mjpegenc.h" - -#include "libmpcodecs/vd_ffmpeg.h" -#include "jpeg_enc.h" - - -/* Begin excessive code duplication ************************************/ -/* Code coming from mpegvideo.c and mjpeg.c in ../libavcodec ***********/ - -static const unsigned short aanscales[64] = { - /* precomputed values scaled up by 14 bits */ - 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, - 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, - 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, - 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, - 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, - 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, - 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446, - 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247 -}; - -static void convert_matrix(MpegEncContext *s, int (*qmat)[64], - uint16_t (*qmat16)[2][64], const uint16_t *quant_matrix, - int bias, int qmin, int qmax) -{ - int qscale; - - for(qscale=qmin; qscale<=qmax; qscale++){ - int i; - if (s->dsp.fdct == ff_jpeg_fdct_islow) { - for (i = 0; i < 64; i++) { - const int j = s->dsp.idct_permutation[i]; - /* 16 <= qscale * quant_matrix[i] <= 7905 - * 19952 <= aanscales[i] * \ - * qscale * quant_matrix[i] <= 205026 - * (1<<36)/19952 >= (1<<36)/(aanscales[i] * \ - * qscale * quant_matrix[i]) >= (1<<36)/249205025 - * 3444240 >= (1<<36)/(aanscales[i] * - * qscale * quant_matrix[i]) >= 275 */ - qmat[qscale][i] = (int)((UINT64_C(1) << (QMAT_SHIFT-3))/ - (qscale * quant_matrix[j])); - } - } else if (s->dsp.fdct == fdct_ifast) { - for(i=0;i<64;i++) { - const int j = s->dsp.idct_permutation[i]; - /* 16 <= qscale * quant_matrix[i] <= 7905 */ - /* 19952 <= aanscales[i] * qscale * quant_matrix[i] <= 249205026 */ - /* (1<<36)/19952 >= (1<<36)/(aanscales[i] * qscale * quant_matrix[i]) >= (1<<36)/249205026 */ - /* 3444240 >= (1<<36)/(aanscales[i] * qscale * quant_matrix[i]) >= 275 */ - - qmat[qscale][i] = (int)((UINT64_C(1) << (QMAT_SHIFT + 11)) / - (aanscales[i] * qscale * quant_matrix[j])); - } - } else { - for(i=0;i<64;i++) { - const int j = s->dsp.idct_permutation[i]; - /* We can safely suppose that 16 <= quant_matrix[i] <= 255 - So 16 <= qscale * quant_matrix[i] <= 7905 - so (1<<19) / 16 >= (1<<19) / (qscale * quant_matrix[i]) >= (1<<19) / 7905 - so 32768 >= (1<<19) / (qscale * quant_matrix[i]) >= 67 - */ - qmat [qscale][i] = (int)((UINT64_C(1) << QMAT_SHIFT_MMX) / (qscale * quant_matrix[j])); - qmat16[qscale][0][i] = (1 << QMAT_SHIFT_MMX) / (qscale * quant_matrix[j]); - - if(qmat16[qscale][0][i]==0 || qmat16[qscale][0][i]==128*256) qmat16[qscale][0][i]=128*256-1; - qmat16[qscale][1][i]= ROUNDED_DIV(bias<<(16-QUANT_BIAS_SHIFT), qmat16[qscale][0][i]); - } - } - } -} - -static inline void encode_dc(MpegEncContext *s, int val, - uint8_t *huff_size, uint16_t *huff_code) -{ - int mant, nbits; - - if (val == 0) { - put_bits(&s->pb, huff_size[0], huff_code[0]); - } else { - mant = val; - if (val < 0) { - val = -val; - mant--; - } - - /* compute the log (XXX: optimize) */ - nbits = 0; - while (val != 0) { - val = val >> 1; - nbits++; - } - - put_bits(&s->pb, huff_size[nbits], huff_code[nbits]); - - put_bits(&s->pb, nbits, mant & ((1 << nbits) - 1)); - } -} - -static void encode_block(MpegEncContext *s, DCTELEM *block, int n) -{ - int mant, nbits, code, i, j; - int component, dc, run, last_index, val; - MJpegContext *m = s->mjpeg_ctx; - uint8_t *huff_size_ac; - uint16_t *huff_code_ac; - - /* DC coef */ - component = (n <= 3 ? 0 : n - 4 + 1); - dc = block[0]; /* overflow is impossible */ - val = dc - s->last_dc[component]; - if (n < 4) { - encode_dc(s, val, m->huff_size_dc_luminance, m->huff_code_dc_luminance); - huff_size_ac = m->huff_size_ac_luminance; - huff_code_ac = m->huff_code_ac_luminance; - } else { - encode_dc(s, val, m->huff_size_dc_chrominance, m->huff_code_dc_chrominance); - huff_size_ac = m->huff_size_ac_chrominance; - huff_code_ac = m->huff_code_ac_chrominance; - } - s->last_dc[component] = dc; - - /* AC coefs */ - - run = 0; - last_index = s->block_last_index[n]; - for(i=1;i<=last_index;i++) { - j = s->intra_scantable.permutated[i]; - val = block[j]; - if (val == 0) { - run++; - } else { - while (run >= 16) { - put_bits(&s->pb, huff_size_ac[0xf0], huff_code_ac[0xf0]); - run -= 16; - } - mant = val; - if (val < 0) { - val = -val; - mant--; - } - - /* compute the log (XXX: optimize) */ - nbits = 0; - while (val != 0) { - val = val >> 1; - nbits++; - } - code = (run << 4) | nbits; - - put_bits(&s->pb, huff_size_ac[code], huff_code_ac[code]); - - put_bits(&s->pb, nbits, mant & ((1 << nbits) - 1)); - run = 0; - } - } - - /* output EOB only if not already 64 values */ - if (last_index < 63 || run != 0) - put_bits(&s->pb, huff_size_ac[0], huff_code_ac[0]); -} - -static inline void clip_coeffs(MpegEncContext *s, DCTELEM *block, int last_index) -{ - int i; - const int maxlevel= s->max_qcoeff; - const int minlevel= s->min_qcoeff; - - for(i=0; i<=last_index; i++){ - const int j = s->intra_scantable.permutated[i]; - int level = block[j]; - - if (level>maxlevel) level=maxlevel; - else if(levels->mjpeg_ctx; - - encode_block(j->s, j->s->block[0], 0); - encode_block(j->s, j->s->block[1], 1); - if (j->bw) { - /* U */ - put_bits(&j->s->pb, m->huff_size_dc_chrominance[0], - m->huff_code_dc_chrominance[0]); - put_bits(&j->s->pb, m->huff_size_ac_chrominance[0], - m->huff_code_ac_chrominance[0]); - /* V */ - put_bits(&j->s->pb, m->huff_size_dc_chrominance[0], - m->huff_code_dc_chrominance[0]); - put_bits(&j->s->pb, m->huff_size_ac_chrominance[0], - m->huff_code_ac_chrominance[0]); - } else { - /* we trick encode_block here so that it uses - * chrominance huffman tables instead of luminance ones - * (see the effect of second argument of encode_block) */ - encode_block(j->s, j->s->block[2], 4); - encode_block(j->s, j->s->block[3], 5); - } -} - -/* this function can take all kinds of YUV colorspaces - * YV12, YVYU, UYVY. The necesary parameters must be set up by the caller - * y_ps means "y pixel size", y_rs means "y row size". - * For YUYV, for example, is u_buf = y_buf + 1, v_buf = y_buf + 3, - * y_ps = 2, u_ps = 4, v_ps = 4, y_rs = u_rs = v_rs. - * - * The actual buffers must be passed with mjpeg_encode_frame, this is - * to make it possible to call encode on the buffer provided by the - * codec in draw_frame. - * - * The data is straightened out at the moment it is put in DCT - * blocks, there are therefore no spurious memcopies involved */ -/* Notice that w must be a multiple of 16 and h must be a multiple of 8 */ -/* We produce YUV422 jpegs, the colors must be subsampled horizontally, - * if the colors are also subsampled vertically, then this function - * performs cheap upsampling (better solution will be: a DCT that is - * optimized in the case that every two rows are the same) */ -/* cu = 0 means 'No cheap upsampling' - * cu = 1 means 'perform cheap upsampling' */ -/* The encoder doesn't know anything about interlacing, the halve height - * needs to be passed and the double rowstride. Which field gets encoded - * is decided by what buffers are passed to mjpeg_encode_frame */ -jpeg_enc_t *jpeg_enc_init(int w, int h, int y_psize, int y_rsize, - int u_psize, int u_rsize, int v_psize, int v_rsize, - int cu, int q, int b) { - jpeg_enc_t *j; - int i = 0; - mp_msg(MSGT_VO, MSGL_V, "JPEnc init: %dx%d %d %d %d %d %d %d\n", - w, h, y_psize, y_rsize, u_psize, - u_rsize, v_psize, v_rsize); - - j = av_malloc(sizeof(jpeg_enc_t)); - if (j == NULL) return NULL; - - j->s = av_malloc(sizeof(MpegEncContext)); - memset(j->s,0x00,sizeof(MpegEncContext)); - if (j->s == NULL) { - av_free(j); - return NULL; - } - - /* info on how to access the pixels */ - j->y_ps = y_psize; - j->u_ps = u_psize; - j->v_ps = v_psize; - j->y_rs = y_rsize; - j->u_rs = u_rsize; - j->v_rs = v_rsize; - - j->s->width = w; - j->s->height = h; - j->s->qscale = q; - - j->s->out_format = FMT_MJPEG; - j->s->intra_only = 1; - j->s->encoding = 1; - j->s->pict_type = FF_I_TYPE; - j->s->y_dc_scale = 8; - j->s->c_dc_scale = 8; - - //FIXME j->s->mjpeg_write_tables = 1; - j->s->mjpeg_vsample[0] = 1; - j->s->mjpeg_vsample[1] = 1; - j->s->mjpeg_vsample[2] = 1; - j->s->mjpeg_hsample[0] = 2; - j->s->mjpeg_hsample[1] = 1; - j->s->mjpeg_hsample[2] = 1; - - j->cheap_upsample = cu; - j->bw = b; - - init_avcodec(); - - if (ff_mjpeg_encode_init(j->s) < 0) { - av_free(j->s); - av_free(j); - return NULL; - } - - /* alloc bogus avctx to keep MPV_common_init from segfaulting */ - j->s->avctx = calloc(sizeof(*j->s->avctx), 1); - /* Set up to encode mjpeg */ - j->s->avctx->codec_id = CODEC_ID_MJPEG; - - /* make MPV_common_init allocate important buffers, like s->block */ - j->s->avctx->thread_count = 1; - - if (MPV_common_init(j->s) < 0) { - av_free(j->s); - av_free(j); - return NULL; - } - - /* correct the value for sc->mb_height */ - j->s->mb_height = j->s->height/8; - j->s->mb_intra = 1; - - j->s->intra_matrix[0] = ff_mpeg1_default_intra_matrix[0]; - for (i = 1; i < 64; i++) - j->s->intra_matrix[i] = av_clip_uint8( - (ff_mpeg1_default_intra_matrix[i]*j->s->qscale) >> 3); - convert_matrix(j->s, j->s->q_intra_matrix, j->s->q_intra_matrix16, - j->s->intra_matrix, j->s->intra_quant_bias, 8, 8); - return j; -} - -int jpeg_enc_frame(jpeg_enc_t *j, unsigned char *y_data, - unsigned char *u_data, unsigned char *v_data, char *bufr) { - int i, k, mb_x, mb_y, overflow; - short int *dest; - unsigned char *source; - /* initialize the buffer */ - - init_put_bits(&j->s->pb, bufr, 1024*256); - - ff_mjpeg_encode_picture_header(j->s); - - j->s->header_bits = put_bits_count(&j->s->pb); - - j->s->last_dc[0] = 128; - j->s->last_dc[1] = 128; - j->s->last_dc[2] = 128; - - for (mb_y = 0; mb_y < j->s->mb_height; mb_y++) { - for (mb_x = 0; mb_x < j->s->mb_width; mb_x++) { - /* conversion 8 to 16 bit and filling of blocks - * must be mmx optimized */ - /* fill 2 Y macroblocks and one U and one V */ - source = mb_y * 8 * j->y_rs + - 16 * j->y_ps * mb_x + y_data; - dest = j->s->block[0]; - for (i = 0; i < 8; i++) { - for (k = 0; k < 8; k++) { - dest[k] = source[k*j->y_ps]; - } - dest += 8; - source += j->y_rs; - } - source = mb_y * 8 * j->y_rs + - (16*mb_x + 8)*j->y_ps + y_data; - dest = j->s->block[1]; - for (i = 0; i < 8; i++) { - for (k = 0; k < 8; k++) { - dest[k] = source[k*j->y_ps]; - } - dest += 8; - source += j->y_rs; - } - if (!j->bw && j->cheap_upsample) { - source = mb_y*4*j->u_rs + - 8*mb_x*j->u_ps + u_data; - dest = j->s->block[2]; - for (i = 0; i < 4; i++) { - for (k = 0; k < 8; k++) { - dest[k] = source[k*j->u_ps]; - dest[k+8] = source[k*j->u_ps]; - } - dest += 16; - source += j->u_rs; - } - source = mb_y*4*j->v_rs + - 8*mb_x*j->v_ps + v_data; - dest = j->s->block[3]; - for (i = 0; i < 4; i++) { - for (k = 0; k < 8; k++) { - dest[k] = source[k*j->v_ps]; - dest[k+8] = source[k*j->v_ps]; - } - dest += 16; - source += j->u_rs; - } - } else if (!j->bw && !j->cheap_upsample) { - source = mb_y*8*j->u_rs + - 8*mb_x*j->u_ps + u_data; - dest = j->s->block[2]; - for (i = 0; i < 8; i++) { - for (k = 0; k < 8; k++) - dest[k] = source[k*j->u_ps]; - dest += 8; - source += j->u_rs; - } - source = mb_y*8*j->v_rs + - 8*mb_x*j->v_ps + v_data; - dest = j->s->block[3]; - for (i = 0; i < 8; i++) { - for (k = 0; k < 8; k++) - dest[k] = source[k*j->v_ps]; - dest += 8; - source += j->u_rs; - } - } - emms_c(); /* is this really needed? */ - - j->s->block_last_index[0] = - j->s->dct_quantize(j->s, j->s->block[0], - 0, 8, &overflow); - if (overflow) clip_coeffs(j->s, j->s->block[0], - j->s->block_last_index[0]); - j->s->block_last_index[1] = - j->s->dct_quantize(j->s, j->s->block[1], - 1, 8, &overflow); - if (overflow) clip_coeffs(j->s, j->s->block[1], - j->s->block_last_index[1]); - - if (!j->bw) { - j->s->block_last_index[4] = - j->s->dct_quantize(j->s, j->s->block[2], - 4, 8, &overflow); - if (overflow) clip_coeffs(j->s, j->s->block[2], - j->s->block_last_index[2]); - j->s->block_last_index[5] = - j->s->dct_quantize(j->s, j->s->block[3], - 5, 8, &overflow); - if (overflow) clip_coeffs(j->s, j->s->block[3], - j->s->block_last_index[3]); - } - zr_mjpeg_encode_mb(j); - } - } - emms_c(); - ff_mjpeg_encode_picture_trailer(j->s); - flush_put_bits(&j->s->pb); - - //FIXME - //if (j->s->mjpeg_write_tables == 1) - // j->s->mjpeg_write_tables = 0; - - return put_bits_ptr(&(j->s->pb)) - j->s->pb.buf; -} - -void jpeg_enc_uninit(jpeg_enc_t *j) { - ff_mjpeg_encode_close(j->s); - av_free(j->s); - av_free(j); -} diff --git a/libvo/jpeg_enc.h b/libvo/jpeg_enc.h deleted file mode 100644 index c3255ad99d..0000000000 --- a/libvo/jpeg_enc.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * straightforward (to be) optimized JPEG encoder for the YUV422 format - * based on MJPEG code from FFmpeg - * - * For an excellent introduction to the JPEG format, see: - * http://www.ece.purdue.edu/~bouman/grad-labs/lab8/pdf/lab.pdf - * - * Copyright (c) 2002, Rik Snel - * parts from FFmpeg Copyright (c) 2000-2002 Fabrice Bellard - * - * 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_JPEG_ENC_H -#define MPLAYER_JPEG_ENC_H - -typedef struct { - struct MpegEncContext *s; - int cheap_upsample; - int bw; - int y_ps; - int u_ps; - int v_ps; - int y_rs; - int u_rs; - int v_rs; -} jpeg_enc_t; - -jpeg_enc_t *jpeg_enc_init(int w, int h, int y_psize, int y_rsize, - int u_psize, int u_rsize, int v_psize, int v_rsize, - int cu, int q, int b); - -int jpeg_enc_frame(jpeg_enc_t *j, unsigned char *y_data, - unsigned char *u_data, unsigned char *v_data, char *bufr); - -void jpeg_enc_uninit(jpeg_enc_t *j); - -#endif /* MPLAYER_JPEG_ENC_H */ diff --git a/libvo/video_out.c b/libvo/video_out.c index caf916d197..679d111e6f 100644 --- a/libvo/video_out.c +++ b/libvo/video_out.c @@ -94,8 +94,6 @@ extern struct vo_driver video_out_tdfxfb; extern struct vo_driver video_out_s3fb; extern struct vo_driver video_out_wii; extern struct vo_driver video_out_null; -extern struct vo_driver video_out_zr; -extern struct vo_driver video_out_zr2; extern struct vo_driver video_out_bl; extern struct vo_driver video_out_fbdev; extern struct vo_driver video_out_fbdev2; @@ -217,10 +215,6 @@ const struct vo_driver *video_out_drivers[] = #ifdef CONFIG_V4L2_DECODER &video_out_v4l2, #endif -#ifdef CONFIG_ZR - &video_out_zr, - &video_out_zr2, -#endif #ifdef CONFIG_BL &video_out_bl, #endif 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#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 ", - "" -}; - -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; -} diff --git a/libvo/vo_zr.h b/libvo/vo_zr.h deleted file mode 100644 index ce13f0fb41..0000000000 --- a/libvo/vo_zr.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * playback on Zoran cards - * - * 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_VO_ZR_H -#define MPLAYER_VO_ZR_H - -#include "m_option.h" - -int vo_zr_parseoption(const m_option_t *conf, const char *opt, const char *param); -void vo_zr_revertoption(const m_option_t *opt, const char *param); - -#endif /* MPLAYER_VO_ZR_H */ diff --git a/libvo/vo_zr2.c b/libvo/vo_zr2.c deleted file mode 100644 index 57addb03f1..0000000000 --- a/libvo/vo_zr2.c +++ /dev/null @@ -1,500 +0,0 @@ -/* - * playback on Zoran cards, based on vo_zr.c - * - * copyright (C) 2001-2005 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "config.h" -#include "videodev_mjpeg.h" -#include "video_out.h" -#include "video_out_internal.h" -#include "mp_msg.h" -#include "subopt-helper.h" -#include "fastmemcpy.h" - -static const vo_info_t info = { - "Zoran ZR360[56]7/ZR36060 Driver (DC10(+)/buz/lml33/MatroxRR)", - "zr2", - "Rik Snel ", - "" -}; - -const LIBVO_EXTERN(zr2) - -typedef struct { - /* options */ - char *subdevice; - - /* information for (and about) the zoran card */ - - unsigned char *buf; /* the JPEGs will be placed here */ - struct mjpeg_requestbuffers zrq; /* info about this buffer */ - - int vdes; /* file descriptor of card */ - int playing; /* 0 or 1 */ - int frame, sync, queue; /* buffer management */ - struct mjpeg_sync zs; /* state information */ - struct mjpeg_params zp; - struct video_capability vc; /* max resolution and so on */ -} vo_zr2_priv_t; - -static vo_zr2_priv_t priv; - -#define ZR2_MJPEG_NBUFFERS 2 -#define ZR2_MJPEG_SIZE 1024*256 - -/* some convenient #define's, is this portable enough? */ -#define DBG2(...) mp_msg(MSGT_VO, MSGL_DBG2, "vo_zr2: " __VA_ARGS__) -#define VERBOSE(...) mp_msg(MSGT_VO, MSGL_V, "vo_zr2: " __VA_ARGS__) -#define ERROR(...) mp_msg(MSGT_VO, MSGL_ERR, "vo_zr2: " __VA_ARGS__) -#define WARNING(...) mp_msg(MSGT_VO, MSGL_WARN, "vo_zr2: " __VA_ARGS__) - -static void stop_playing(vo_zr2_priv_t *p) { - if (p->playing) { - p->frame = -1; - if (ioctl(p->vdes, MJPIOC_QBUF_PLAY, &p->frame) < 0) - ERROR("error stopping playback\n"); - p->playing = 0; - p->sync = 0; - p->queue = 0; - p->frame = 0; - } -} - -static const char *guess_device(const char *suggestion, int inform) { - struct stat vstat; - int res; - static const char * const devs[] = { - "/dev/video", - "/dev/video0", - "/dev/v4l/video0", - "/dev/v4l0", - "/dev/v4l", - NULL - }; - const char * const *dev = devs; - - if (suggestion) { - if (!*suggestion) { - ERROR("error: specified device name is empty string\n"); - return NULL; - } - - res = stat(suggestion, &vstat); - if (res == 0 && S_ISCHR(vstat.st_mode)) { - if (inform) VERBOSE("using device %s\n", suggestion); - return suggestion; - } else { - if (res != 0) ERROR("%s does not exist\n", suggestion); - else ERROR("%s is no character device\n", suggestion); - /* don't try to be smarter than the user, just exit */ - return NULL; - } - } - - while (*(++dev) != NULL) { - if (stat(*dev, &vstat) == 0 && S_ISCHR(vstat.st_mode)) { - VERBOSE("guessed video device %s\n", *dev); - return *dev; - } - dev++; - } - - ERROR("unable to find video device\n"); - - return NULL; -} - -static int query_format(uint32_t format) { - if (format==IMGFMT_ZRMJPEGNI || - format==IMGFMT_ZRMJPEGIT || - format==IMGFMT_ZRMJPEGIB) - return VFCAP_CSP_SUPPORTED|VFCAP_CSP_SUPPORTED_BY_HW; - return 0; -} - -static uint32_t draw_image(mp_image_t *mpi) { - vo_zr2_priv_t *p = &priv; - int size = (int)mpi->planes[1]; - if (size > (int)p->zrq.size) { - ERROR("incoming JPEG image (size=%d) doesn't fit in buffer\n", - size); - return VO_FALSE; - } - - /* looking for free buffer */ - if (p->queue - p->sync < (int)p->zrq.count) p->frame = p->queue; - else { - if (ioctl(p->vdes, MJPIOC_SYNC, &p->zs) < 0) { - ERROR("error waiting for buffer to become free\n"); - return VO_FALSE; - } - p->frame = p->zs.frame; - p->sync++; - } - - /* copy the jpeg image to the buffer which we acquired */ - fast_memcpy(p->buf + p->zrq.size*p->frame, mpi->planes[0], size); - - return VO_TRUE; -} - -static const char *normstring(int norm) { - switch (norm) { - case VIDEO_MODE_PAL: - return "PAL"; - case VIDEO_MODE_NTSC: - return "NTSC"; - case VIDEO_MODE_SECAM: - return "SECAM"; - case VIDEO_MODE_AUTO: - return "auto"; - } - return "undefined"; -} - -static int get_norm(const char *n) { - if (!strcmp(n, "PAL")) return VIDEO_MODE_PAL; - if (!strcmp(n, "NTSC")) return VIDEO_MODE_NTSC; - if (!strcmp(n, "SECAM")) return VIDEO_MODE_SECAM; - if (!strcmp(n, "auto")) return VIDEO_MODE_AUTO; - return -1; /* invalid */ -} - -static int nc(void *normp) { - const char **norm = normp; - if (get_norm(*norm) == -1) { - ERROR("norm \"%s\" is not supported, choose from PAL, NTSC, SECAM and auto\n", *norm); - return 0; - } else return 1; -} - -static int pbc(void *prebufp) { - int *prebuf = prebufp; - if (*prebuf) WARNING("prebuffering is not yet supported\n"); - return 1; -} - -static int preinit(const char *arg) { - vo_zr2_priv_t *p = &priv; - const char *dev = NULL; - char *dev_arg = NULL, *norm_arg = NULL; - int norm = VIDEO_MODE_AUTO, prebuf = 0; - const opt_t subopts[] = { /* don't want warnings with -Wall... */ - { "dev", OPT_ARG_MSTRZ, &dev_arg, NULL }, - { "prebuf", OPT_ARG_BOOL, &prebuf, pbc }, - { "norm", OPT_ARG_MSTRZ, &norm_arg, nc }, - { NULL, 0, NULL, NULL } - }; - - VERBOSE("preinit() called with arg: %s\n", arg); - memset(p, 0, sizeof(*p)); /* set defaults */ - p->vdes = -1; - - if (subopt_parse(arg, subopts)) { - mp_msg(MSGT_VO, MSGL_FATAL, - "Allowed suboptions for -vo zr2 are:\n" - "- dev=DEVICE (default: %s)\n" - "- norm=PAL|NTSC|SECAM|auto (default: auto)\n" - "- prebuf/noprebuf (default:" - " noprebuf)\n" - "\n" - "Example: mplayer -vo zr2:dev=/dev/video1:" - "norm=PAL movie.avi\n\n" - , guess_device(NULL, 0)); - free(norm_arg); - free(dev_arg); - return -1; - } - - /* interpret the strings we got from subopt_parse */ - if (norm_arg) { - norm = get_norm(norm_arg); - free(norm_arg); - } - - if (dev_arg) dev = dev_arg; - - dev = guess_device(dev, 1); - if (!dev) { - free(dev_arg); - uninit(); - return 1; - } - - p->vdes = open(dev, O_RDWR); - if (p->vdes < 0) { - ERROR("error opening %s: %s\n", dev, strerror(errno)); - free(dev_arg); - uninit(); - return 1; - } - - free(dev_arg); - - /* check if we really are dealing with a zoran card */ - if (ioctl(p->vdes, MJPIOC_G_PARAMS, &p->zp) < 0) { - ERROR("%s probably is not a DC10(+)/buz/lml33\n", dev); - uninit(); - return 1; - } - - VERBOSE("kernel driver version %d.%d, current norm is %s\n", - p->zp.major_version, p->zp.minor_version, - normstring(p->zp.norm)); - - /* changing the norm in the zoran_params and MJPIOC_S_PARAMS - * does nothing the last time I tried, so bail out if the norm - * is not correct */ - if (norm != VIDEO_MODE_AUTO && p->zp.norm != norm) { - ERROR("mplayer currently can't change the video norm, " - "change it with (eg.) XawTV and retry.\n"); - uninit(); - return 1; - } - - /* gather useful information */ - if (ioctl(p->vdes, VIDIOCGCAP, &p->vc) < 0) { - ERROR("error getting video capabilities from %s\n", dev); - uninit(); - return 1; - } - - VERBOSE("card reports maxwidth=%d, maxheight=%d\n", - p->vc.maxwidth, p->vc.maxheight); - - /* according to the mjpegtools source, some cards return a bogus - * vc.maxwidth, correct it here. If a new zoran card appears with a - * maxwidth different 640, 720 or 768 this code may lead to problems */ - if (p->vc.maxwidth != 640 && p->vc.maxwidth != 768) { - VERBOSE("card probably reported bogus width (%d), " - "changing to 720\n", p->vc.maxwidth); - p->vc.maxwidth = 720; - } - - p->zrq.count = ZR2_MJPEG_NBUFFERS; - p->zrq.size = ZR2_MJPEG_SIZE; - - if (ioctl(p->vdes, MJPIOC_REQBUFS, &p->zrq)) { - ERROR("error requesting %d buffers of size %d\n", - ZR2_MJPEG_NBUFFERS, ZR2_MJPEG_NBUFFERS); - uninit(); - return 1; - } - - VERBOSE("got %ld buffers of size %ld (wanted %d buffers of size %d)\n", - p->zrq.count, p->zrq.size, ZR2_MJPEG_NBUFFERS, - ZR2_MJPEG_SIZE); - - p->buf = (unsigned char*)mmap(0, p->zrq.count*p->zrq.size, - PROT_READ|PROT_WRITE, MAP_SHARED, p->vdes, 0); - - if (p->buf == MAP_FAILED) { - ERROR("error mapping requested buffers: %s", strerror(errno)); - uninit(); - return 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 fields = 1, top_first = 1, err = 0; - int stretchx = 1, stretchy = 1; - struct mjpeg_params zptmp; - vo_zr2_priv_t *p = &priv; - VERBOSE("config() called\n"); - - /* paranoia check */ - if (!query_format(format)) { - ERROR("called with wrong format, should be impossible\n"); - return 1; - } - - if ((int)height > p->vc.maxheight) { - ERROR("input height %d is too large, maxheight=%d\n", - height, p->vc.maxheight); - err = 1; - } - - if (format != IMGFMT_ZRMJPEGNI) { - fields = 2; - if (format == IMGFMT_ZRMJPEGIB) - top_first = 0; - } else if ((int)height > p->vc.maxheight/2) { - ERROR("input is too high (%d) for non-interlaced playback" - "max=%d\n", height, p->vc.maxheight); - err = 1; - } - - if (width%16 != 0) { - ERROR("input width=%d, must be multiple of 16\n", width); - err = 1; - } - - if (height%(fields*8) != 0) { - ERROR("input height=%d, must be multiple of %d\n", - height, 2*fields); - err = 1; - } - - /* we assume sample_aspect = 1 */ - if (fields == 1) { - if (2*d_width <= (uint32_t)p->vc.maxwidth) { - VERBOSE("stretching x direction to preserve aspect\n"); - d_width *= 2; - } else VERBOSE("unable to preserve aspect, screen width " - "too small\n"); - } - - if (d_width == width) stretchx = 1; - else if (d_width == 2*width) stretchx = 2; -#if 0 /* do minimal stretching for now */ - else if (d_width == 4*width) stretchx = 4; - else WARNING("d_width must be {1,2,4}*width, using defaults\n"); - - if (d_height == height) stretchy = 1; - else if (d_height == 2*height) stretchy = 2; - else if (d_height == 4*height) stretchy = 4; - else WARNING("d_height must be {1,2,4}*height, using defaults\n"); -#endif - - if (stretchx*width > (uint32_t)p->vc.maxwidth) { - ERROR("movie to be played is too wide, width=%d>maxwidth=%d\n", - width*stretchx, p->vc.maxwidth); - err = 1; - } - - if (stretchy*height > (uint32_t)p->vc.maxheight) { - ERROR("movie to be played is too heigh, height=%d>maxheight" - "=%d\n", height*stretchy, p->vc.maxheight); - err = 1; - } - - if (err == 1) return 1; - - /* some video files (eg. concatenated MPEG files), make MPlayer - * call config() during playback while no parameters have changed. - * We make configuration changes to a temporary params structure, - * compare it with the old params structure and only apply the new - * config if it is different from the old one. */ - memcpy(&zptmp, &p->zp, sizeof(zptmp)); - - /* translate the configuration to zoran understandable format */ - zptmp.decimation = 0; - zptmp.HorDcm = stretchx; - zptmp.VerDcm = stretchy; - zptmp.TmpDcm = 1; - zptmp.field_per_buff = fields; - zptmp.odd_even = top_first; - - /* center the image on screen */ - zptmp.img_x = (p->vc.maxwidth - width*stretchx)/2; - zptmp.img_y = (p->vc.maxheight - height*stretchy*(3-fields))/4; - - zptmp.img_width = stretchx*width; - zptmp.img_height = stretchy*height/fields; - - VERBOSE("tv: %dx%d, out: %dx%d+%d+%d, in: %ux%u %s%s%s\n", - p->vc.maxwidth, p->vc.maxheight, - zptmp.img_width, 2*zptmp.img_height, - zptmp.img_x, 2*zptmp.img_y, - width, height, (fields == 1) ? "non-interlaced" : "", - (fields == 2 && top_first == 1) - ? "interlaced top first" : "", - (fields == 2 && top_first == 0) - ? "interlaced bottom first" : ""); - - if (memcmp(&zptmp, &p->zp, sizeof(zptmp))) { - /* config differs, we must update */ - memcpy(&p->zp, &zptmp, sizeof(zptmp)); - stop_playing(p); - if (ioctl(p->vdes, MJPIOC_S_PARAMS, &p->zp) < 0) { - ERROR("error writing display params to card\n"); - return 1; - } - VERBOSE("successfully written display parameters to card\n"); - } else VERBOSE("config didn't change, no need to write it to card\n"); - - return 0; -} - -static int control(uint32_t request, void *data) { - switch (request) { - case VOCTRL_QUERY_FORMAT: - return query_format(*((uint32_t*)data)); - case VOCTRL_DRAW_IMAGE: - return draw_image(data); - } - return VO_NOTIMPL; -} - -static int draw_frame(uint8_t *src[]) { - return 0; -} - -static int draw_slice(uint8_t *image[], int stride[], - int w, int h, int x, int y) { - return 0; -} - -static void draw_osd(void) { -} - -static void flip_page(void) { - vo_zr2_priv_t *p = &priv; - /* queueing the buffer for playback */ - /* queueing the first buffer automatically starts playback */ - if (p->playing == 0) p->playing = 1; - if (ioctl(p->vdes, MJPIOC_QBUF_PLAY, &p->frame) < 0) - ERROR("error queueing buffer for playback\n"); - else p->queue++; -} - -static void check_events(void) { -} - -static void uninit(void) { - vo_zr2_priv_t *p = &priv; - VERBOSE("uninit() called (may be called from preinit() on error)\n"); - - stop_playing(p); - - if (p->buf && munmap(p->buf, p->zrq.size*p->zrq.count)) - ERROR("error munmapping buffer: %s\n", strerror(errno)); - - if (p->vdes >= 0) close(p->vdes); - free(p->subdevice); -}