diff options
-rw-r--r-- | libmpcodecs/Makefile | 2 | ||||
-rw-r--r-- | libmpcodecs/vd.c | 29 | ||||
-rw-r--r-- | libmpcodecs/vd_divx4.c | 127 | ||||
-rw-r--r-- | libmpcodecs/vd_odivx.c | 193 | ||||
-rw-r--r-- | libmpcodecs/vd_vfw.c | 105 |
5 files changed, 448 insertions, 8 deletions
diff --git a/libmpcodecs/Makefile b/libmpcodecs/Makefile index f5c5ce510a..45ad475782 100644 --- a/libmpcodecs/Makefile +++ b/libmpcodecs/Makefile @@ -3,7 +3,7 @@ include ../config.mak LIBNAME = libmpcodecs.a -SRCS=dec_video.c vd.c vd_null.c vd_cinepak.c vd_qtrpza.c vd_ffmpeg.c vd_dshow.c +SRCS=dec_video.c vd.c vd_null.c vd_cinepak.c vd_qtrpza.c vd_ffmpeg.c vd_dshow.c vd_vfw.c vd_odivx.c vd_divx4.c OBJS=$(SRCS:.c=.o) diff --git a/libmpcodecs/vd.c b/libmpcodecs/vd.c index 05604677cf..779171bd16 100644 --- a/libmpcodecs/vd.c +++ b/libmpcodecs/vd.c @@ -26,6 +26,10 @@ extern vd_functions_t mpcodecs_vd_cinepak; extern vd_functions_t mpcodecs_vd_qtrpza; extern vd_functions_t mpcodecs_vd_ffmpeg; extern vd_functions_t mpcodecs_vd_dshow; +extern vd_functions_t mpcodecs_vd_vfw; +extern vd_functions_t mpcodecs_vd_vfwex; +extern vd_functions_t mpcodecs_vd_odivx; +extern vd_functions_t mpcodecs_vd_divx4; vd_functions_t* mpcodecs_vd_drivers[] = { &mpcodecs_vd_null, @@ -34,9 +38,19 @@ vd_functions_t* mpcodecs_vd_drivers[] = { #ifdef USE_LIBAVCODEC &mpcodecs_vd_ffmpeg, #endif +#ifdef USE_WIN32DLL #ifdef USE_DIRECTSHOW &mpcodecs_vd_dshow, #endif + &mpcodecs_vd_vfw, + &mpcodecs_vd_vfwex, +#endif +#ifdef USE_DIVX + &mpcodecs_vd_odivx, +#ifdef NEW_DECORE + &mpcodecs_vd_divx4, +#endif +#endif NULL }; @@ -56,30 +70,31 @@ static int static_idx=0; // Note: buffer allocation may be moved to mpcodecs_config_vo() later... mp_image_t* mpcodecs_get_image(sh_video_t *sh, int mp_imgtype, int mp_imgflag, int w, int h){ mp_image_t* mpi=NULL; + int w2=(mp_imgflag&MP_IMGFLAG_ACCEPT_STRIDE)?((w+15)&(~15)):w; // Note: we should call libvo first to check if it supports direct rendering // and if not, then fallback to software buffers: switch(mp_imgtype){ case MP_IMGTYPE_EXPORT: // mpi=new_mp_image(w,h); - if(!export_images[0]) export_images[0]=new_mp_image(w,h); + if(!export_images[0]) export_images[0]=new_mp_image(w2,h); mpi=export_images[0]; break; case MP_IMGTYPE_STATIC: - if(!static_images[0]) static_images[0]=new_mp_image(w,h); + if(!static_images[0]) static_images[0]=new_mp_image(w2,h); mpi=static_images[0]; break; case MP_IMGTYPE_TEMP: - if(!temp_images[0]) temp_images[0]=new_mp_image(w,h); + if(!temp_images[0]) temp_images[0]=new_mp_image(w2,h); mpi=temp_images[0]; break; case MP_IMGTYPE_IPB: if(!(mp_imgflag&MP_IMGFLAG_READABLE)){ // B frame: - if(!temp_images[0]) temp_images[0]=new_mp_image(w,h); + if(!temp_images[0]) temp_images[0]=new_mp_image(w2,h); mpi=temp_images[0]; break; } case MP_IMGTYPE_IP: - if(!static_images[static_idx]) static_images[static_idx]=new_mp_image(w,h); + if(!static_images[static_idx]) static_images[static_idx]=new_mp_image(w2,h); mpi=static_images[static_idx]; static_idx^=1; break; @@ -88,8 +103,8 @@ mp_image_t* mpcodecs_get_image(sh_video_t *sh, int mp_imgtype, int mp_imgflag, i mpi->type=mp_imgtype; mpi->flags&=~(MP_IMGFLAG_PRESERVE|MP_IMGFLAG_READABLE); mpi->flags|=mp_imgflag&(MP_IMGFLAG_PRESERVE|MP_IMGFLAG_READABLE); - if((mpi->width!=w || mpi->height!=h) && !(mpi->flags&MP_IMGFLAG_DIRECT)){ - mpi->width=w; + if((mpi->width!=w2 || mpi->height!=h) && !(mpi->flags&MP_IMGFLAG_DIRECT)){ + mpi->width=w2; mpi->height=h; if(mpi->flags&MP_IMGFLAG_ALLOCATED){ // need to re-allocate buffer memory: diff --git a/libmpcodecs/vd_divx4.c b/libmpcodecs/vd_divx4.c new file mode 100644 index 0000000000..edb3bed0c8 --- /dev/null +++ b/libmpcodecs/vd_divx4.c @@ -0,0 +1,127 @@ +#include <stdio.h> +#include <stdlib.h> +#include <assert.h> + +#include "config.h" +#include "mp_msg.h" +#include "help_mp.h" + +#ifdef USE_DIVX +#ifdef NEW_DECORE + +#include "codec-cfg.h" +#include "../libvo/img_format.h" + +#include "stream.h" +#include "demuxer.h" +#include "stheader.h" + +#include "vd.h" +#include "vd_internal.h" + +static vd_info_t info = { +#ifdef DECORE_DIVX5 + "DivX5Linux lib (divx4 mode)", +#else + "DivX4Linux lib (divx4 mode)", +#endif + "divx4", + VFM_DIVX4, + "A'rpi", + "http://www.divx.com", + "native codecs" +}; + +LIBVD_EXTERN(divx4) + +#include <decore.h> + +// to set/get/query special features/parameters +static int control(sh_video_t *sh,int cmd,void* arg,...){ + switch(cmd){ + case VDCTRL_QUERY_MAX_PP_LEVEL: + return 9; // for divx4linux + case VDCTRL_SET_PP_LEVEL: { + DEC_SET dec_set; + int quality=*((int*)arg); + if(quality<0 || quality>9) quality=9; + dec_set.postproc_level=quality*10; + decore(0x123,DEC_OPT_SETPP,&dec_set,NULL); + return CONTROL_OK; + } + + } + + return CONTROL_UNKNOWN; +} + +// init driver +static int init(sh_video_t *sh){ + DEC_PARAM dec_param; +// DEC_SET dec_set; + int bits=16; + memset(&dec_param,0,sizeof(dec_param)); + + mpcodecs_config_vo(sh,sh->disp_w,sh->disp_h,IMGFMT_YUY2); + + switch(sh->codec->outfmt[sh->outfmtidx]){ + case IMGFMT_YV12: dec_param.output_format=DEC_YV12;bits=12;break; + case IMGFMT_YUY2: dec_param.output_format=DEC_YUY2;break; + case IMGFMT_UYVY: dec_param.output_format=DEC_UYVY;break; + case IMGFMT_I420: dec_param.output_format=DEC_420;bits=12;break; + case IMGFMT_BGR15: dec_param.output_format=DEC_RGB555_INV;break; + case IMGFMT_BGR16: dec_param.output_format=DEC_RGB565_INV;break; + case IMGFMT_BGR24: dec_param.output_format=DEC_RGB24_INV;bits=24;break; + case IMGFMT_BGR32: dec_param.output_format=DEC_RGB32_INV;bits=32;break; + default: + mp_msg(MSGT_DECVIDEO,MSGL_ERR,"Unsupported out_fmt: 0x%X\n",sh->codec->outfmt[sh->outfmtidx]); + return 0; + } + dec_param.x_dim = sh->disp_w; + dec_param.y_dim = sh->disp_h; + decore(0x123, DEC_OPT_INIT, &dec_param, NULL); +// dec_set.postproc_level = divx_quality; +// decore(0x123, DEC_OPT_SETPP, &dec_set, NULL); + + mp_msg(MSGT_DECVIDEO,MSGL_V,"INFO: DivX4Linux video codec init OK!\n"); + + return 1; +} + +// uninit driver +static void uninit(sh_video_t *sh){ + decore(0x123,DEC_OPT_RELEASE,NULL,NULL); +} + +//mp_image_t* mpcodecs_get_image(sh_video_t *sh, int mp_imgtype, int mp_imgflag, int w, int h); + +// decode a frame +static mp_image_t* decode(sh_video_t *sh,void* data,int len,int flags){ + mp_image_t* mpi; + DEC_FRAME dec_frame; + + if(len<=0) return NULL; // skipped frame + + dec_frame.length = len; + dec_frame.bitstream = data; + dec_frame.render_flag = (flags&3)?0:1; + + mpi=mpcodecs_get_image(sh, MP_IMGTYPE_TEMP, MP_IMGFLAG_PRESERVE | MP_IMGFLAG_ACCEPT_WIDTH, + sh->disp_w, sh->disp_h); + if(!mpi) return NULL; + + dec_frame.bmp=mpi->planes[0]; + dec_frame.stride=mpi->width; + +#ifdef DECORE_DIVX5 + decore(0x123, DEC_OPT_FRAME, &dec_frame, NULL); +#else + decore(0x123, (sh->format==mmioFOURCC('D','I','V','3'))?DEC_OPT_FRAME_311:DEC_OPT_FRAME, &dec_frame, NULL); +#endif + + return mpi; +} + +#endif +#endif + diff --git a/libmpcodecs/vd_odivx.c b/libmpcodecs/vd_odivx.c new file mode 100644 index 0000000000..7e02e110e5 --- /dev/null +++ b/libmpcodecs/vd_odivx.c @@ -0,0 +1,193 @@ +#include <stdio.h> +#include <stdlib.h> +#include <assert.h> + +#include "config.h" +#include "mp_msg.h" +#include "help_mp.h" + +#ifdef USE_DIVX + +#include "codec-cfg.h" +#include "../libvo/img_format.h" + +#include "stream.h" +#include "demuxer.h" +#include "stheader.h" + +#include "vd.h" +#include "vd_internal.h" + +static vd_info_t info = { +#ifdef NEW_DECORE +#ifdef DECORE_DIVX5 + "DivX5Linux lib (odivx mode)", +#else + "DivX4Linux lib (odivx mode)", +#endif +#else + "Opendivx 0.48 codec", +#endif + "odivx", + VFM_ODIVX, + "A'rpi", +#ifdef NEW_DECORE + "http://www.divx.com", +#else + "http://www.projectmayo.org", +#endif + "native codecs" +}; + +LIBVD_EXTERN(odivx) + +#ifndef NEW_DECORE +#include "opendivx/decore.h" +#else +#include <decore.h> +#endif + +//**************************************************************************// +// The OpenDivX stuff: +//**************************************************************************// + +#ifndef NEW_DECORE + +static unsigned char *opendivx_src[3]; +static int opendivx_stride[3]; + +// callback, the opendivx decoder calls this for each frame: +void convert_linux(unsigned char *puc_y, int stride_y, + unsigned char *puc_u, unsigned char *puc_v, int stride_uv, + unsigned char *bmp, int width_y, int height_y){ + +// printf("convert_yuv called %dx%d stride: %d,%d\n",width_y,height_y,stride_y,stride_uv); + + opendivx_src[0]=puc_y; + opendivx_src[1]=puc_u; + opendivx_src[2]=puc_v; + + opendivx_stride[0]=stride_y; + opendivx_stride[1]=stride_uv; + opendivx_stride[2]=stride_uv; +} +#endif + + +// to set/get/query special features/parameters +static int control(sh_video_t *sh,int cmd,void* arg,...){ + switch(cmd){ + case VDCTRL_QUERY_MAX_PP_LEVEL: +#ifdef NEW_DECORE + return 9; // for divx4linux +#else + return GET_PP_QUALITY_MAX; // for opendivx +#endif + case VDCTRL_SET_PP_LEVEL: { + DEC_SET dec_set; + int quality=*((int*)arg); +#ifdef NEW_DECORE + if(quality<0 || quality>9) quality=9; + dec_set.postproc_level=quality*10; +#else + if(quality<0 || quality>GET_PP_QUALITY_MAX) quality=GET_PP_QUALITY_MAX; + dec_set.postproc_level=getPpModeForQuality(quality); +#endif + decore(0x123,DEC_OPT_SETPP,&dec_set,NULL); + return CONTROL_OK; + } + + } + + return CONTROL_UNKNOWN; +} + +// init driver +static int init(sh_video_t *sh){ + DEC_PARAM dec_param; +// DEC_SET dec_set; + memset(&dec_param,0,sizeof(dec_param)); +#ifdef NEW_DECORE + dec_param.output_format=DEC_USER; +#else + dec_param.color_depth = 32; +#endif + dec_param.x_dim = sh->disp_w; + dec_param.y_dim = sh->disp_h; + decore(0x123, DEC_OPT_INIT, &dec_param, NULL); +// dec_set.postproc_level = divx_quality; +// decore(0x123, DEC_OPT_SETPP, &dec_set, NULL); + + mp_msg(MSGT_DECVIDEO,MSGL_V,"INFO: OpenDivX video codec init OK!\n"); + + mpcodecs_config_vo(sh,sh->disp_w,sh->disp_h,IMGFMT_YV12); + return 1; +} + +// uninit driver +static void uninit(sh_video_t *sh){ + decore(0x123,DEC_OPT_RELEASE,NULL,NULL); +} + +//mp_image_t* mpcodecs_get_image(sh_video_t *sh, int mp_imgtype, int mp_imgflag, int w, int h); + +// decode a frame +static mp_image_t* decode(sh_video_t *sh,void* data,int len,int flags){ + mp_image_t* mpi; + DEC_FRAME dec_frame; +#ifdef NEW_DECORE + DEC_PICTURE dec_pic; +#endif + + if(len<=0) return NULL; // skipped frame + + dec_frame.length = len; + dec_frame.bitstream = data; + dec_frame.render_flag = (flags&3)?0:1; + +#ifdef NEW_DECORE + dec_frame.bmp=&dec_pic; + dec_pic.y=dec_pic.u=dec_pic.v=NULL; +#ifdef DECORE_DIVX5 + decore(0x123, DEC_OPT_FRAME, &dec_frame, NULL); +#else + decore(0x123, (sh->format==mmioFOURCC('D','I','V','3'))?DEC_OPT_FRAME_311:DEC_OPT_FRAME, &dec_frame, NULL); +#endif +#else + // opendivx: + opendivx_src[0]=NULL; + decore(0x123, 0, &dec_frame, NULL); +#endif + + if(flags&3) return NULL; // framedrop + +#ifdef NEW_DECORE + if(!dec_pic.y) return NULL; // bad frame +#else + if(!opendivx_src[0]) return NULL; // bad frame +#endif + + mpi=mpcodecs_get_image(sh, MP_IMGTYPE_EXPORT, MP_IMGFLAG_PRESERVE, + sh->disp_w, sh->disp_h); + if(!mpi) return NULL; + +#ifdef NEW_DECORE + mpi->planes[0]=dec_pic.y; + mpi->planes[1]=dec_pic.u; + mpi->planes[2]=dec_pic.v; + mpi->stride[0]=dec_pic.stride_y; + mpi->stride[1]=mpi->stride[2]=dec_pic.stride_uv; +#else + mpi->planes[0]=opendivx_src[0]; + mpi->planes[1]=opendivx_src[1]; + mpi->planes[2]=opendivx_src[2]; + mpi->stride[0]=opendivx_stride[0]; + mpi->stride[1]=opendivx_stride[1]; + mpi->stride[2]=opendivx_stride[2]; +#endif + + return mpi; +} + +#endif + diff --git a/libmpcodecs/vd_vfw.c b/libmpcodecs/vd_vfw.c new file mode 100644 index 0000000000..20053053bc --- /dev/null +++ b/libmpcodecs/vd_vfw.c @@ -0,0 +1,105 @@ +#include <stdio.h> +#include <stdlib.h> + +#include "config.h" +#ifdef USE_WIN32DLL + +#include "mp_msg.h" +#include "help_mp.h" + +#include "codec-cfg.h" +#include "../libvo/img_format.h" + +#include "stream.h" +#include "demuxer.h" +#include "stheader.h" + +#include "vd.h" +#include "vd_internal.h" + +#include "dll_init.h" + +static vd_info_t info_vfw = { + "Win32/VfW video codecs", + "vfw", + VFM_VFW, + "A'rpi", + "based on http://avifile.sf.net", + "win32 codecs" +}; + +static vd_info_t info_vfwex = { + "Win32/VfWex video codecs", + "vfwex", + VFM_VFWEX, + "A'rpi", + "based on http://avifile.sf.net", + "win32 codecs" +}; + +#define info info_vfw +LIBVD_EXTERN(vfw) +#undef info + +#define info info_vfwex +LIBVD_EXTERN(vfwex) +#undef info + +// to set/get/query special features/parameters +static int control(sh_video_t *sh,int cmd,void* arg,...){ + switch(cmd){ + case VDCTRL_QUERY_MAX_PP_LEVEL: + return 9; + case VDCTRL_SET_PP_LEVEL: + vfw_set_postproc(sh,10*(*((int*)arg))); + return CONTROL_OK; + } + return CONTROL_UNKNOWN; +} + +// init driver +static int init(sh_video_t *sh){ + unsigned int out_fmt; + if(!init_vfw_video_codec(sh,(sh->codec->driver==VFM_VFWEX))) return 0; + mp_msg(MSGT_DECVIDEO,MSGL_V,"INFO: Win32 video codec init OK!\n"); + mpcodecs_config_vo(sh,sh->disp_w,sh->disp_h,IMGFMT_YUY2); +// out_fmt=sh->codec->outfmt[sh->outfmtidx]; + return 1; +} + +// uninit driver +static void uninit(sh_video_t *sh){ + +} + +//mp_image_t* mpcodecs_get_image(sh_video_t *sh, int mp_imgtype, int mp_imgflag, int w, int h); + +// decode a frame +static mp_image_t* decode(sh_video_t *sh,void* data,int len,int flags){ + mp_image_t* mpi; + int ret; + if(len<=0) return NULL; // skipped frame + + mpi=mpcodecs_get_image(sh, MP_IMGTYPE_IP, MP_IMGFLAG_ACCEPT_WIDTH, + sh->disp_w, sh->disp_h); + if(!mpi){ // temporary! + printf("couldn't allocate image for cinepak codec\n"); + return NULL; + } + + // set buffer: + sh->our_out_buffer=mpi->planes[0]; + + // set stride: (trick discovered by Andreas Ackermann - thanx!) + sh->bih->biWidth=mpi->width; //mpi->stride[0]/(mpi->bpp/8); + sh->o_bih.biWidth=mpi->width; //mpi->stride[0]/(mpi->bpp/8); + + if((ret=vfw_decode_video(sh,data,len,flags&3,(sh->codec->driver==VFM_VFWEX) ))){ + mp_msg(MSGT_DECVIDEO,MSGL_WARN,"Error decompressing frame, err=%d\n",ret); + return NULL; + } + + return mpi; +} + +#endif |