diff options
Diffstat (limited to 'libmpcodecs')
-rw-r--r-- | libmpcodecs/vd.c | 4 | ||||
-rw-r--r-- | libmpcodecs/vd_zrmjpeg.c | 249 | ||||
-rw-r--r-- | libmpcodecs/vf.c | 4 | ||||
-rw-r--r-- | libmpcodecs/vf_zrmjpeg.c | 1049 |
4 files changed, 0 insertions, 1306 deletions
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 <rsnel@cube.dyndns.org> - * - based on vd_mpegpes.c by A'rpi (C) 2002-2003 - * - guess_mjpeg_type code stolen from lav_io.c (C) 2000 Rainer Johanni - * <Rainer@Johanni.de> 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 <stdio.h> -#include <stdlib.h> - -#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 <snel@phys.uu.nl>", - "Rik Snel <snel@phys.uu.nl>", - "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; @@ -144,9 +143,6 @@ static const vf_info_t* const filter_list[]={ &vf_info_screenshot, &vf_info_uspp, #endif -#ifdef CONFIG_ZR - &vf_info_zrmjpeg, -#endif &vf_info_dvbscale, &vf_info_cropdetect, &vf_info_test, 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 <rsnel@cube.dyndns.org> - * - 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 <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <inttypes.h> - -#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, " |