Log in

View Full Version : ConvertYV12ToYUY2VerticalReduceBy2


scmccarthy
12th November 2002, 12:06
Q: How can you convert to YUY2 from YV12 without chroma interpolation?
A: By resizing the luma.

If x is luma and o is chroma, YV12 is like:

xxxxx
o o o
xxxxx
xxxxx
o o o
xxxxx
xxxxx etc.

So I wrote a filter that uses a (1/2,1/2) kernal to average the lines of luma above and below each chroma sample like this:

const int row_size = src->GetRowSize(PLANAR_U);
const int height = src->GetHeight(PLANAR_U);

for (int y = 0; y < height; y++) {
for (int x = 0; x < row_size; x++) {
yuv2p[x*4 + 0] = (srcpY[x*2] + srcpY[x*2+src_pitchY])>>1;
yuv2p[x*4 + 1] = srcpU[x];
yuv2p[x*4 + 2] = (srcpY[x*2+1] + srcpY[x*2+1+src_pitchY])>>1;
yuv2p[x*4 + 3] = srcpV[x];
}
srcpY += src_pitchY*2;
srcpU += src_pitchUV;
srcpV += src_pitchUV;
yuv2p += dst_pitch;
}

return dst;

This is the first filter I ever wrote. I think it might be useful as an example code since it is almost as simple as Invert with one important exception. It taught me what to put in the brackets after the GenericVideoFilter function:

ConvertYV12ToYUY2VRBy2(PClip _child) : GenericVideoFilter(_child) {
vi.height >>= 1;
vi.pixel_type = VideoInfo::CS_YUY2;
child->SetCacheHints(CACHE_NOTHING,0);
}

So if anyone is wondering, this is how you output a different size and pixel type than what you read as input. I had a lot of trouble finding this and even mentioned my trouble in another thread. I read the ConvertToYV12() function in the sources, but overlooked where the pixel type was being changed, since it is not near the main loop. Thanks ShOdan for not interpolating yet, it was much easier to follow that way. Hopefully, now people will always have the choice whether to interpolate or halve the frame.

The idea behind the filter is to see if the colors look better or sharper if I convert without interpolation, but with the chroma perfectly cited on the luma. Also I figured this could be used instead of VerticalReduceBy2(). It is very fast (for a filter that does not use mmx) and looks very good. This actually represents an idea I have that color space conversions and resizing can be optimized if done together. It might minimize the degradation due either to the conversion of resizing. I also noticed that there are many flavors of RGB:

RGB709, RGB601, RGB240M, RGBEDU, RGB255 for blackcode 0 on computers, and RGB219. Now I am on the quest for the perfect matrix to preserve gamma and color fidelity. The answer being that there is no perfect version because the absolute best is probubly different for interlaced, framebased, PAL, of NTSC sources. So my answer will be to try a couple and see.

I hope you like it.

Oh, and here's the attachment:

scmccarthy
12th November 2002, 12:16
I started learning about color spaces from the Avisynth.org FAQ Section 3 Filters and Color Spaces, MSDN YUV FAQ link.

sh0dan
12th November 2002, 13:26
Unless I'm mistaking, your filter has problems with interlaced material. You interpolate every second luma line = blended deinterlacing, but preserve chroma interlacing. (every second line = one field).

Even the internal YV12 -> YUY2 doesn't handle interlaced material properly, so don't worry (too much anyway). It doesn't even interpolate chroma yet.

Now I got blankclip working, conversion is next on the list.

scmccarthy
12th November 2002, 18:57
@Sh0dan

My message was a little too long to read. I did mention in there that I am glad you did not interpolate the chroma yet; that made it easier to follow. I already had studied YV12 enough to see that chroma needed interpolation. I was struggling with whether to make height and width PlaneY sized or PlaneU and what the multipliers needed to be. Choosig PlaneU is clearly the way to go when processing the planes in parallel.

I am working on a very simple and dirty (3/4,1/4) kernal interpolation that is plugin compatible with the version in Avisynth 2.5 that I plan to post in this thread as an example and I might extend it into a real shot at a good interpolation, if it works.


By the way, are you planning to support NV12? The quote from MSDN http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/YUVFormats.asp is:

NV12 is the preferred 4:2:0 pixel format for DirectX VA.

NV12 combines the chroma into one plane, and has a PlaneY the same as YV12. PlaneUV has the same width as PlaneY, but half the height, perhaps making it easier to process in some cases. The chroma samples alternate uvuvuv... similiar to how YUY2 treats all the samples. Converting between the two is a matter of rearranging the samples. The reason I would like to see it supported is that I imagine that Direct Show supports it.

sh0dan
12th November 2002, 20:28
Originally posted by scmccarthy
@Sh0dan
By the way, are you planning to support NV12?

No - I have no current plans for it - YV12 is far more used than NV12 (I've never seen it used actually). I can't really see any advantages in using NV12, except slightly better alignment, but YV12 is actually more flexible that way.

trbarry
12th November 2002, 21:24
Q: How can you convert to YUY2 from YV12 without chroma interpolation?
A: By resizing the luma.

scmccarthy -

Somewhat special purpose, but a clever idea. ;)

- Tom

scmccarthy
13th November 2002, 00:56
@ trbarry

Thanks.

I figure anybody who has frame based mpeg-2 in YV12 and wants to use VerticalReduceBy2() really shouldn't now. Interpolation, no matter how well done is always lossy. The counter argument is that whatever damage interpolation does would be completely masked by sizing down anyway. So the only real argument maybe is that it saves processing time not to interpolate if you are just going to throw out the advantage of the interpolation by downsizing later.

But basically the idea is: it is a healthy thing to start thinking in terms of processing the luma and chroma independently of one another. I am hoping that someone will optimize it using MMX code:rolleyes:
Mainly to see how it is done.

scmccarthy
13th November 2002, 01:09
@sh0dan

I'd like to see NV12 added to avisynth.h like this:

// Specific colorformats
enum { CS_UNKNOWN = 0,
CS_BGR24 = 1<<0 | CS_BGR | CS_INTERLEAVED,
CS_BGR32 = 1<<1 | CS_BGR | CS_INTERLEAVED,
CS_YUY2 = 1<<2 | CS_YUV | CS_INTERLEAVED,
CS_YV12 = 1<<3 | CS_YUV | CS_PLANAR, // y-v-u, planar
CS_I420 = 1<<4 | CS_YUV | CS_PLANAR, // y-u-v, planar
CS_IYUV = 1<<4 | CS_YUV | CS_PLANAR, // same as above
CS_NV12 = 1<<5 | CS_YUV | CS_PLANAR
};
int pixel_type; // changed to int as of 2.5

But now that I put it like that, I see that it is Planar with interleaved chroma. So it doesn't fit in either catagory. I'm curious to see if WMP would play it, though.