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