[MPlayer-dev-eng] ok to add new vf?

D Richard Felker III dalias at aerifal.cx
Fri Jul 26 20:58:01 CEST 2002


Hey, I've just written a new video filter and I wanna make sure it's
ok to add it to cvs before I commit. The file is attached. The basic
idea behind this filter, halfpack, is as follows:

Suppose you want to display a hires movie on a low resolution device,
e.g. a tv screen. If your video device supports scaling overlays down
properly, no problem, right? Well some cards don't support scaling
down at all, and others (g200) use nearest neighbor when scaling down,
resulting in horrible output quality.

The normal solution would be to use the sw scaler to scale down. But
suppose you have to scale a 640x480 movie down to 640x240. Assuming
your codec outputs a planar colorspace such as yv12, the vertical
chroma resolution after scalind down will be 120. You've thrown away
half your chroma samples for no reason, since 240 lines of chroma
would still fit perfectly fine.

Here's where -vop halfpack comes in. It converts planar yuv input to
packed yuv (yuy2) output, halving the vertical luma resolution but
keeping all the original chroma samples.

Right now it still has a few problems -- averaging two lines of luma
doesn't make for the best quality when scaling down, direct rendering
doesn't seem to be taking effect, and I'm not positive it works with
plane-swapped input -- but it can't break or affect anything else in
mplayer, so I'd like to go ahead and get it in cvs if that's ok. Oh,
it's also probably a bit slow -- I'll implement an asm version when I
get a chance, and hopefully fix dr.

Rich


-------------- next part --------------
#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 "vf.h"

#include "../libvo/fastmemcpy.h"
#include "../postproc/rgb2rgb.h"


static void halfpack(unsigned char *dst, unsigned char *src[3],
		     unsigned int dststride, unsigned int srcstride[3],
		     int w, int h)
{
	int i, j;
	unsigned char *y1, *y2, *u, *v;
	unsigned int dstinc, yinc, uinc, vinc;

	y1 = src[0];
	y2 = src[0] + srcstride[0];
	u = src[1];
	v = src[2];

	dstinc = dststride - 2*w;
	yinc = 2*srcstride[0] - w;
	uinc = srcstride[1] - w/2;
	vinc = srcstride[2] - w/2;

	//printf("sup %d %d\n", dstinc, yinc);
	for (i = h/2; i; i--) {
		for (j = w/2; j; j--) {
			*dst++ = ((int)*y1++ + *y2++)/2;
			*dst++ = *u++;
			*dst++ = ((int)*y1++ + *y2++)/2;
			*dst++ = *v++;
		}
		y1 += yinc;
		y2 += yinc;
		u += uinc;
		v += vinc;
		dst += dstinc;
	}
}

static void put_image(struct vf_instance_s* vf, mp_image_t *mpi)
{
	mp_image_t *dmpi;

	// hope we'll get DR buffer:
	dmpi=vf_get_image(vf->next, IMGFMT_YUY2,
			  MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
			  mpi->w, mpi->h/2);
	
	halfpack(dmpi->planes[0], mpi->planes,
		 dmpi->stride[0], mpi->stride,
		 mpi->w, mpi->h);

	vf_next_put_image(vf,dmpi);
}

static int config(struct vf_instance_s* vf,
		  int width, int height, int d_width, int d_height,
		  unsigned int flags, unsigned int outfmt)
{
	return vf_next_config(vf, width, height/2, d_width, d_height, flags, IMGFMT_YUY2);
}


static int query_format(struct vf_instance_s* vf, unsigned int fmt)
{
	switch (fmt) {
	case IMGFMT_YV12:
	case IMGFMT_IYUV:
	case IMGFMT_I420:
		return vf_next_query_format(vf,IMGFMT_YUY2);
	}
	return 0;
}


static int open(vf_instance_t *vf, char* args)
{
	vf->config=config;
	vf->query_format=query_format;
	vf->put_image=put_image;
	return 1;
}

vf_info_t vf_info_halfpack = {
	"planar yuv -> packed, half height",
	"halfpack",
	"Richard Felker",
	"",
	open
};



More information about the MPlayer-dev-eng mailing list