Mercurial > mplayer.hg
changeset 11386:229079491864
addition of special image formats for Zoran MJPEG, and vd_zrmjpeg.c
the zoran passthrough filter for the new vo_zr2.
author | rik |
---|---|
date | Tue, 04 Nov 2003 19:58:37 +0000 |
parents | cd0088334aea |
children | 19fe73d1cb03 |
files | libmpcodecs/Makefile libmpcodecs/img_format.c libmpcodecs/img_format.h libmpcodecs/mp_image.h libmpcodecs/vd.c libmpcodecs/vd_zrmjpeg.c |
diffstat | 6 files changed, 250 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/libmpcodecs/Makefile Tue Nov 04 19:28:32 2003 +0000 +++ b/libmpcodecs/Makefile Tue Nov 04 19:58:37 2003 +0000 @@ -11,7 +11,7 @@ VIDEO_SRCS_LIB=vd_libmpeg2.c vd_nuv.c vd_lzo.c VIDEO_SRCS_NAT=vd_null.c vd_cinepak.c vd_qtrpza.c vd_raw.c vd_hmblck.c vd_msvidc.c vd_fli.c vd_qtrle.c vd_qtsmc.c vd_roqvideo.c vd_cyuv.c vd_msrle.c vd_mpegpes.c vd_lcl.c vd_mtga.c vd_sgi.c vd_qt8bps.c -VIDEO_SRCS_OPT=vd_realvid.c vd_ffmpeg.c vd_dshow.c vd_dmo.c vd_vfw.c vd_vfwex.c vd_odivx.c vd_divx4.c vd_xanim.c vd_xvid.c vd_libdv.c vd_qtvideo.c vd_theora.c +VIDEO_SRCS_OPT=vd_realvid.c vd_ffmpeg.c vd_dshow.c vd_dmo.c vd_vfw.c vd_vfwex.c vd_odivx.c vd_divx4.c vd_zrmjpeg.c vd_xanim.c vd_xvid.c vd_libdv.c vd_qtvideo.c vd_theora.c VIDEO_SRCS=dec_video.c vd.c $(VIDEO_SRCS_NAT) $(VIDEO_SRCS_LIB) $(VIDEO_SRCS_OPT) VFILTER_SRCS=vf.c vf_vo.c vf_crop.c vf_expand.c vf_scale.c vf_format.c vf_yuy2.c vf_flip.c vf_rgb2bgr.c vf_rotate.c vf_mirror.c vf_palette.c vf_lavc.c vf_dvbscale.c vf_cropdetect.c vf_test.c vf_noise.c vf_yvu9.c vf_rectangle.c vf_lavcdeint.c vf_eq.c vf_eq2.c vf_halfpack.c vf_dint.c vf_1bpp.c vf_bmovl.c vf_2xsai.c vf_unsharp.c vf_swapuv.c vf_il.c vf_boxblur.c vf_sab.c vf_smartblur.c vf_perspective.c vf_down3dright.c vf_field.c vf_denoise3d.c vf_hqdn3d.c vf_detc.c vf_telecine.c vf_tfields.c vf_ivtc.c vf_ilpack.c vf_dsize.c vf_decimate.c vf_softpulldown.c vf_tinterlace.c vf_pullup.c pullup.c vf_framestep.c vf_tile.c vf_delogo.c vf_fil.c vf_hue.c vf_spp.c
--- a/libmpcodecs/img_format.c Tue Nov 04 19:28:32 2003 +0000 +++ b/libmpcodecs/img_format.c Tue Nov 04 19:58:37 2003 +0000 @@ -55,6 +55,9 @@ case IMGFMT_YUVP: return("Packed YUVP"); case IMGFMT_UYVP: return("Packed UYVP"); case IMGFMT_MPEGPES: return("Mpeg PES"); + case IMGFMT_ZRMJPEGNI: return("Zoran MJPEG non-interlaced"); + case IMGFMT_ZRMJPEGIT: return("Zoran MJPEG top field first"); + case IMGFMT_ZRMJPEGIB: return("Zoran MJPEG bottom field first"); case IMGFMT_XVMC_MOCO_MPEG2: return("MPEG1/2 Motion Compensation"); case IMGFMT_XVMC_IDCT_MPEG2: return("MPEG1/2 Motion Compensation and IDCT"); }
--- a/libmpcodecs/img_format.h Tue Nov 04 19:28:32 2003 +0000 +++ b/libmpcodecs/img_format.h Tue Nov 04 19:58:37 2003 +0000 @@ -77,6 +77,11 @@ /* Compressed Formats */ #define IMGFMT_MPEGPES (('M'<<24)|('P'<<16)|('E'<<8)|('S')) +/* Formats that are understood by zoran chips, we include + * non-interlaced, interlaced top-first, interlaced bottom-first */ +#define IMGFMT_ZRMJPEGNI (('Z'<<24)|('R'<<16)|('N'<<8)|('I')) +#define IMGFMT_ZRMJPEGIT (('Z'<<24)|('R'<<16)|('I'<<8)|('T')) +#define IMGFMT_ZRMJPEGIB (('Z'<<24)|('R'<<16)|('I'<<8)|('B')) // I think that this code could not be used by any other codec/format #define IMGFMT_XVMC 0x1DC70000
--- a/libmpcodecs/mp_image.h Tue Nov 04 19:28:32 2003 +0000 +++ b/libmpcodecs/mp_image.h Tue Nov 04 19:58:37 2003 +0000 @@ -102,6 +102,12 @@ mpi->bpp=0; return; } + if(out_fmt == IMGFMT_ZRMJPEGNI || + out_fmt == IMGFMT_ZRMJPEGIT || + out_fmt == IMGFMT_ZRMJPEGIB){ + mpi->bpp=0; + return; + } if(IMGFMT_IS_XVMC(out_fmt)){ mpi->bpp=0; return;
--- a/libmpcodecs/vd.c Tue Nov 04 19:28:32 2003 +0000 +++ b/libmpcodecs/vd.c Tue Nov 04 19:58:37 2003 +0000 @@ -55,6 +55,7 @@ extern vd_functions_t mpcodecs_vd_sgi; extern vd_functions_t mpcodecs_vd_libmpeg2; extern vd_functions_t mpcodecs_vd_mpegpes; +extern vd_functions_t mpcodecs_vd_zrmjpeg; extern vd_functions_t mpcodecs_vd_realvid; extern vd_functions_t mpcodecs_vd_xvid; extern vd_functions_t mpcodecs_vd_libdv; @@ -113,6 +114,9 @@ &mpcodecs_vd_libmpeg2, #endif &mpcodecs_vd_mpegpes, +#ifdef HAVE_ZR + &mpcodecs_vd_zrmjpeg, +#endif #ifdef USE_REALCODECS &mpcodecs_vd_realvid, #endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmpcodecs/vd_zrmjpeg.c Tue Nov 04 19:58:37 2003 +0000 @@ -0,0 +1,231 @@ +/* + * Copyright (C) 2003 Rik Snel <snel@phys.uu.nl>, license GPL v2 + * - 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 + */ +#include <stdio.h> +#include <stdlib.h> + +#include "config.h" +#include "mp_msg.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 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_inited; + 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 CONTROL_TRUE; + 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, ncomps, 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_inited) { + 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_inited = 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; +}