diff -u a/m_option.c~ a/m_option.c --- a/m_option.c~ 2007-10-07 21:49:33.000000000 +0200 +++ a/m_option.c 2008-02-21 13:40:35.000000000 +0100 @@ -1049,6 +1049,7 @@ {"argb", IMGFMT_ARGB}, {"bgra", IMGFMT_BGRA}, {"abgr", IMGFMT_ABGR}, + {"ba81", IMGFMT_BA81}, {"mjpeg", IMGFMT_MJPEG}, {"mjpg", IMGFMT_MJPEG}, { NULL, 0 } diff -u a/etc/codecs.conf~ a/etc/codecs.conf --- a/etc/codecs.conf~ 2007-10-07 21:49:33.000000000 +0200 +++ a/etc/codecs.conf 2008-02-21 12:52:29.000000000 +0100 @@ -2304,6 +2304,14 @@ fourcc y800,Y800 out Y800,Y8 +videocodec rawba81 + info "RAW BA81/BYR1" + status untested + driver raw + format 0x0 + fourcc ba81,BA81 + out BA81 + ; NULL codec - for testing. videocodec null diff -u a/libmpcodecs/img_format.h~ a/libmpcodecs/img_format.h --- a/libmpcodecs/img_format.h~ 2007-10-07 21:49:25.000000000 +0200 +++ a/libmpcodecs/img_format.h 2008-02-21 12:27:26.000000000 +0100 @@ -91,6 +91,11 @@ #define IMGFMT_YUVP 0x50565559 #define IMGFMT_UYVP 0x50565955 +/* Bayer Formats */ +#define IMGFMT_BA81 0x31384142 +#define IMGFMT_BYR1 IMGFMT_BA81 +#define IMGFMT_BYR2 0x32525942 + /* Compressed Formats */ #define IMGFMT_MPEGPES (('M'<<24)|('P'<<16)|('E'<<8)|('S')) #define IMGFMT_MJPEG (('M')|('J'<<8)|('P'<<16)|('G'<<24)) diff -u a/libmpcodecs/vd.c~ a/libmpcodecs/vd.c --- a/libmpcodecs/vd.c~ 2007-10-07 21:49:25.000000000 +0200 +++ a/libmpcodecs/vd.c 2008-02-21 14:50:58.000000000 +0100 @@ -334,7 +334,8 @@ // 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=vf_get_image(sh->vfilter,sh->codec->outfmt[sh->outfmtidx],mp_imgtype,mp_imgflag,w,h); - mpi->x=mpi->y=0; + if (mpi) + mpi->x=mpi->y=0; return mpi; } diff -u a/libmpcodecs/vf.c~ a/libmpcodecs/vf.c --- a/libmpcodecs/vf.c~ 2007-10-07 21:49:25.000000000 +0200 +++ a/libmpcodecs/vf.c 2008-02-21 14:56:10.000000000 +0100 @@ -99,6 +99,7 @@ extern vf_info_t vf_info_blackframe; extern vf_info_t vf_info_geq; extern vf_info_t vf_info_ow; +extern vf_info_t vf_info_ba81; // list of available filters: static vf_info_t* filter_list[]={ @@ -193,6 +194,7 @@ &vf_info_yadif, &vf_info_blackframe, &vf_info_ow, + &vf_info_ba81, NULL }; @@ -326,7 +328,9 @@ mpi->height=h; mpi->chroma_height=(h + (1<chroma_y_shift) - 1)>>mpi->chroma_y_shift; } } - if(!mpi->bpp) mp_image_setfmt(mpi,outfmt); + if(!mpi->bpp) + mp_image_setfmt(mpi,outfmt); + mp_msg(MSGT_VFILTER, MSGL_DBG2, "flags %x, type %x\n", mpi->flags, mpi->type); if(!(mpi->flags&MP_IMGFLAG_ALLOCATED) && mpi->type>MP_IMGTYPE_EXPORT){ // check libvo first! @@ -394,7 +398,9 @@ } } if(mpi->flags&MP_IMGFLAG_DRAW_CALLBACK) - if(vf->start_slice) vf->start_slice(vf,mpi); + if(vf->start_slice) + vf->start_slice(vf,mpi); + if(!(mpi->flags&MP_IMGFLAG_TYPE_DISPLAYED)){ mp_msg(MSGT_DECVIDEO,MSGL_V,"*** [%s] %s%s mp_image_t, %dx%dx%dbpp %s %s, %d bytes\n", vf->info->name, diff -u a/libmpcodecs/Makefile~ a/libmpcodecs/Makefile --- a/libmpcodecs/Makefile~ 2007-10-07 21:49:25.000000000 +0200 +++ a/libmpcodecs/Makefile 2008-02-21 12:17:13.000000000 +0100 @@ -94,6 +94,7 @@ vf_yuy2.c \ vf_yvu9.c \ vf_ow.c \ + vf_ba81.c # These filters use private headers and do not work with shared libavcodec. SRCS_COMMON-$(LIBAVCODEC_A) += vf_fspp.c \ diff -u a/libmpcodecs/mp_image.h~ a/libmpcodecs/mp_image.h --- a/libmpcodecs/mp_image.h~ 2007-10-07 21:49:25.000000000 +0200 +++ a/libmpcodecs/mp_image.h 2008-02-21 13:49:12.000000000 +0100 @@ -129,6 +129,10 @@ mpi->flags|=MP_IMGFLAG_SWAPPED; return; } + if (out_fmt == IMGFMT_BA81) { + mpi->bpp = 8; + return; + } mpi->flags|=MP_IMGFLAG_YUV; mpi->num_planes=3; switch(out_fmt){ diff -u a/stream/tv.c~ a/stream/tv.c --- a/stream/tv.c~ 2007-10-07 21:49:26.000000000 +0200 +++ a/stream/tv.c 2008-02-21 13:29:17.000000000 +0100 @@ -320,7 +320,8 @@ IMGFMT_RGB32, IMGFMT_RGB24, IMGFMT_RGB16, - IMGFMT_RGB15 + IMGFMT_RGB15, + IMGFMT_BA81 }; if (funcs->control(tvh->priv, TVI_CONTROL_IS_VIDEO, 0) != TVI_CONTROL_TRUE) @@ -351,6 +352,7 @@ case IMGFMT_BGR24: case IMGFMT_BGR16: case IMGFMT_BGR15: + case IMGFMT_BA81: break; default: mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TV_UnknownImageFormat,tvh->tv_param->outfmt); diff -u a/codec-cfg.c~ a/codec-cfg.c --- a/codec-cfg.c~ 2007-10-07 21:49:33.000000000 +0200 +++ a/codec-cfg.c 2008-02-21 12:52:06.000000000 +0100 @@ -174,6 +174,8 @@ {"RGB1", IMGFMT_RGB|1}, {"BGR1", IMGFMT_BGR|1}, + {"BA81", IMGFMT_BA81}, + {"MPES", IMGFMT_MPEGPES}, {"ZRMJPEGNI", IMGFMT_ZRMJPEGNI}, {"ZRMJPEGIT", IMGFMT_ZRMJPEGIT}, diff -u a/libmpcodecs/mp_image.c~ a/libmpcodecs/mp_image.c --- a/libmpcodecs/mp_image.c~ 2007-10-07 21:49:25.000000000 +0200 +++ a/libmpcodecs/mp_image.c 2008-02-22 16:06:33.000000000 +0100 @@ -17,6 +17,9 @@ mp_image_t* alloc_mpi(int w, int h, unsigned long int fmt) { mp_image_t* mpi = new_mp_image(w,h); + if (!mpi) + return mpi; + mp_image_setfmt(mpi,fmt); // IF09 - allocate space for 4. plane delta info - unused if (mpi->imgfmt == IMGFMT_IF09) diff -u a/libmenu/vf_menu.c~ a/libmenu/vf_menu.c --- a/libmenu/vf_menu.c~ 2007-10-07 21:49:32.000000000 +0200 +++ a/libmenu/vf_menu.c 2008-02-22 16:05:11.000000000 +0100 @@ -155,7 +155,8 @@ } if(!pause_mpi) pause_mpi = alloc_mpi(mpi->w,mpi->h,mpi->imgfmt); - copy_mpi(pause_mpi,mpi); + if (pause_mpi) + copy_mpi(pause_mpi, mpi); mp_input_queue_cmd(mp_input_parse_cmd("pause")); go2pause = 2; break; diff -u /dev/null a/libmpcodecs/vf_ba81.c --- /dev/null 2008-02-22 09:54:27.890267157 +0100 +++ a/libmpcodecs/vf_ba81.c 2008-02-22 12:23:43.000000000 +0100 @@ -0,0 +1,280 @@ +#include +#include +#include +#include + +#include "config.h" +#include "mp_msg.h" +#include "help_mp.h" + +#include "img_format.h" +#include "mp_image.h" +#include "vf.h" + +#include "libvo/fastmemcpy.h" + +//===========================================================================// + +/* + * The Bayer colour pattern: + * + * GRGRGR....GR + * BGBGBG....BG + * ............ + * ............ + * GRGRGR....GR + * BGBGBG....BG + * + * Which also means it must have even height and width + */ + +static int config(struct vf_instance_s* vf, + int width, int height, int d_width, int d_height, + unsigned int flags, unsigned int outfmt) +{ +#if 0 +/* + * Example from DOCS/tech/libmpcodecs.txt. Do we really have + * to set vf->priv->{w,h} here? + */ + + // use d_width/d_height if not set by user: + if(vf->priv->w==-1) vf->priv->w=d_width; + if(vf->priv->h==-1) vf->priv->h=d_height; +#endif + + if (vf_next_query_format(vf, IMGFMT_BGR16) <= 0) { + mp_msg(MSGT_VFILTER, MSGL_WARN, MSGTR_MPCODECS_WarnNextFilterDoesntSupport, "BGR16"); + return 0; + } + + return vf_next_config(vf, width, height, d_width, d_height, flags, IMGFMT_BGR16); +} + +/* This produces an BGR16 5:6:5 format from 8-bit b, g, r */ +#define bgr16(b, g, r) (((b) >> 3) | (((g) & 0xfc) << 3) | (((r) & 0xf8) << 8)) +/* BGR16 5:5:5 format from 8-bit b, g, r */ +//#define bgr16(b, g, r) (((b) >> 3) | (((g) & 0xf8) << 1) | (((r) & 0xf8) << 8)) + +static inline unsigned char uavg4(unsigned char a, unsigned char b, + unsigned char c, unsigned char d) +{ + unsigned int s = a, t = b, u = c, v = d; + return (s + t + u + v) >> 2; +} + +static void dump_clr(unsigned char code, unsigned char c, unsigned short s) +{ + mp_msg(MSGT_VFILTER, MSGL_V, "%c%u: r%u:g%u:b%u\n", code, + code == 'g' ? c >> 2 : c >> 3, + (s & 0xf800) >> 11, (s & 0x7e0) >> 5, s & 0x1f); +} + +static int put_image(struct vf_instance_s* vf, mp_image_t *mpi, double pts) +{ + mp_image_t *dmpi; + int y, x, i; + uint16_t *d; + unsigned char *s, *srow, *drow; + static int dump; + + dump++; + + // hope we'll get DR buffer: + dmpi = vf_get_image(vf->next, IMGFMT_BGR16, + MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE, + mpi->w, mpi->h); + + if (!dmpi) + return 0; + + d = (uint16_t *)dmpi->planes[0]; + s = mpi->planes[0]; + + mp_msg(MSGT_VFILTER, MSGL_DBG2, "BA81: source %p, destination: %p, stride: %u|%u\n", + s, d, mpi->stride[0], dmpi->stride[0]); + + /* The first row: GRGR... Below is a BGBG... */ + + /* The first pixel: B below, R to the right, G at the origin */ + *d++ = bgr16(s[mpi->w], s[0], s[1]); + + /* The first row without ends */ + for (x = 1; x < mpi->w - 1;) { + *d++ = bgr16((s[x + mpi->w - 1] + s[x + mpi->w + 1]) / 2, + (s[x - 1] + s[x + 1]) / 2, + s[x]); + x++; + *d++ = bgr16(s[x + mpi->w], + s[x], + (s[x - 1] + s[x + 1]) / 2); + x++; + } + + /* The last pixel in the first row: B down left, R at the point, G to the left and down */ + *d = bgr16(s[2 * mpi->w - 2], + (s[mpi->w - 2] + s[mpi->w * 2 - 1]) / 2, + s[mpi->w - 1]); + + drow = dmpi->planes[0] + dmpi->stride[0]; + d = (uint16_t *)drow; + srow = mpi->planes[0] + mpi->stride[0]; + x = mpi->stride[0]; + + for (y = 1; y < mpi->h / 2; y++) { + + /* + * EVEN ROW + */ + + mp_msg(MSGT_VFILTER, MSGL_DBG2, "BA81: row %d: s %p, d %p\n", + y * 2, s + x, d); + + /* First column */ + /* I do not want to divide by 3, so, I'll only take green pixels + * above and below */ + *d++ = bgr16(s[x], + (s[x - mpi->w] + s[x + mpi->w]) / 2, + (s[x - mpi->w + 1] + s[x + mpi->w + 1]) / 2); + x++; + + /* Middle */ + for (i = 1; i < mpi->w / 2; i++) { + *d++ = bgr16((s[x - 1] + s[x + 1]) / 2, + s[x], + (s[x - mpi->w] + s[x + mpi->w]) / 2); + + if (dump == 5 && y < 5 && i < 5) + dump_clr('g', s[x], *(d - 1)); + x++; +#if 1 + *d++ = bgr16(s[x], + (s[x - 1] + s[x + 1] + + s[x - mpi->w] + s[x + mpi->w]) / 4, + (s[x - mpi->w - 1] + s[x - mpi->w + 1] + + s[x + mpi->w - 1] + s[x + mpi->w + 1]) / 4); +#else + *d++ = bgr16(s[x], + uavg4(s[x - 1], s[x + 1], + s[x - mpi->w], s[x + mpi->w]), + uavg4(s[x - mpi->w - 1], s[x - mpi->w + 1], + s[x + mpi->w - 1], s[x + mpi->w + 1])); +#endif + + if (dump == 5 && y < 5 && i < 5) + dump_clr('b', s[x], *(d - 1)); + x++; + } + + /* Last column */ + *d = bgr16(s[x - 1], + s[x], + (s[x - mpi->w] + s[x + mpi->w]) / 2); + + drow += dmpi->stride[0]; + d = (uint16_t *)drow; + srow += mpi->stride[0]; + x = srow - mpi->planes[0]; + + /* + * ODD ROW + */ + + mp_msg(MSGT_VFILTER, MSGL_DBG2, "BA81: row %d: s %p, d %p\n", + y * 2 + 1, s + x, d); + + /* First column */ + *d++ = bgr16((s[x - mpi->w] + s[x + mpi->w]) / 2, + s[x], + s[x + 1]); + x++; + + /* Middle */ + for (i = 1; i < mpi->w / 2; i++) { + *d++ = bgr16((s[x - mpi->w - 1] + s[x - mpi->w + 1] + + s[x + mpi->w - 1] + s[x + mpi->w + 1]) / 4, + (s[x - 1] + s[x + 1] + + s[x - mpi->w] + s[x + mpi->w]) / 4, + s[x]); + + if (dump == 5 && y < 5 && i < 5) + dump_clr('r', s[x], *(d - 1)); + x++; + *d++ = bgr16((s[x - mpi->w] + s[x + mpi->w]) / 2, + s[x], + (s[x - 1] + s[x + 1]) / 2); + + if (dump == 5 && y < 5 && i < 5) + dump_clr('g', s[x], *(d - 1)); + x++; + } + + /* Last column */ + *d++ = bgr16((s[x - mpi->w - 1] + s[x + mpi->w + 1]) / 2, + (s[x - mpi->w] + s[x + mpi->w]) / 2, + s[x]); + + drow += dmpi->stride[0]; + d = (uint16_t *)drow; + srow += mpi->stride[0]; + x = srow - mpi->planes[0]; + } + + /* Last row */ + /* First pixel */ + *d++ = bgr16(s[x], + (s[x - mpi->w] + s[x + 1]) / 2, + s[x - mpi->w + 1]); + x++; + + /* The last row without ends */ + for (i = 1; i < mpi->w - 1; i++) { + *d++ = bgr16((s[x - 1] + s[x + 1]) / 2, + s[x], + s[x - mpi->w]); + x++; + *d++ = bgr16(s[x], + (s[x - 1] + s[x + 1]) / 2, + (s[x - mpi->w - 1] + s[x - mpi->w + 1]) / 2); + x++; + } + + /* The last pixel */ + *d = bgr16(s[x - 1], s[x], s[x - mpi->w]); + + /* Old code below... */ + + vf_clone_mpi_attributes(dmpi, mpi); + + return vf_next_put_image(vf,dmpi, pts); +} + +//===========================================================================// + +static int query_format(struct vf_instance_s* vf, unsigned int fmt) +{ + /* width and height have to be even */ + if (fmt == IMGFMT_BA81) + return vf_next_query_format(vf, IMGFMT_BGR16) & (~VFCAP_CSP_SUPPORTED_BY_HW); + return 0; +} + +static int open(vf_instance_t *vf, char* args) +{ + vf->config = config; + vf->put_image = put_image; + vf->query_format = query_format; + + return 1; +} + +vf_info_t vf_info_ba81 = { + "fast BA81->BGR16 conversion", + "ba81", + "G. Liakhovetski ", + "", + open, + NULL +}; + +//===========================================================================//