PDA

View Full Version : RawSource YV12 output bad


patrick_
16th February 2009, 18:34
I'm trying to read a RAW video file 720x480 in YV12.

The original file was created writing sequential the data obtained by:
env->BitBlt((BYTE*)buf, stride, f->GetReadPtr(), f->GetPitch(), f->GetRowSize(), f->GetHeight());
*f is a PVideoFrame

I use rawsource.dll to read the data:
RawSource("I:\somevideo.raw", 720, 480, "YV12")

Here's the output:
http://img13.imageshack.us/img13/2853/rawyv12tk6.jpg

The problem is obvious, but I don't know how to fix it.

Thanks in advance for any help.

Dark Shikari
16th February 2009, 18:52
Pitch is not necessarily equal to Width.

patrick_
16th February 2009, 19:39
Thanks for helping, but I don't understand what I should change.
RawSource (string "file", int "widht", int "height", string "pixel_type", string "index", bool "show")
and looking at the source, it seems that it already takes in account that pitch isn't necessary the same as width

Or are you saying that the RAWFile may have wrong data? I've tested it with RGB output and it displayed fine. I didn't test YV12, because windows (.NET) supports natively only RGB.
and from avisynth source: BitBlt(BYTE* dstp, int dst_pitch, const BYTE* srcp, int src_pitch, int row_size, int height)
to me it seems that the code is fine.

edit: Note that the frame offset is always correct (and I supose the size), it just seems that the channels (planes?) are messed up.

kemuri-_9
16th February 2009, 21:13
you say you're using it correctly but yet you don't show where you defined and instantiated 'buf' or 'stride' in your call of BitBlt to prove it.
posting a sample of your source video would be helpful as well.

patrick_
16th February 2009, 23:20
when writing a RAW stride doesn't really matter, because there's no need to write more than pixelwidth * bpp, because there's no need to align data in the file.
buf is a pointer to a memory location.

kemuri-_9
16th February 2009, 23:37
BitBlt is meant for copying frames directly,
it uses the pitches to advance the src and dst pointers to where the data for the next line should be read from/written to.
giving the wrong pitch size could have it overwrite previously written data or put data too far past where expected later.

if you only wanted to create raw YV12 files, you should of used avs2yuv.

provide a sample of your yv12 file, it's possibly corrupt from the incorrect writing of data.

patrick_
17th February 2009, 00:19
My program creates the RAW files. AVS2YUV isn't an option.

For the syntax, I already understood how BitBlt is working. My Raw's Stride/Pitch = BPP * Width / 8 and the source's Pitch is whatever PVideoFrame->GetPitch(). BitBlt should take care of the difference between them, that's why it's asking for both.
But looking at the RAW, it may be true that something is wrong over there, because the output is different from avs2avi.

So any suggestion about how to copy correctly framedata to a memory location? Would just setting the stride in the RAW to mod 16 (that's the value of GetPitch) be a solution? I guess that way I can also read the file using BitBlt and that will make things a lot easier (and probably faster).
- I'm thinking about these solutions, but actually none of them should be one, because BitBlt and RawSource already take Pitch into account.

kemuri-_9
17th February 2009, 01:41
All i can tell you is that AVS stores the Y,U,V planes of YV12 data in separate memory locations, so that straight copying isn't quite going to work...
this is probably why a single call of BitBlt isn't working (probably need 3 separate calls...)

looking at the source code for RawSource is probably going to be your best bet as it denotes how it reads the data from the file, so it should give you the concepts for how to write data to a file.

the section of code within

if (vi.IsPlanar()) {
...
} else if (!stricmp(pixel_type,"YV16")) {

is what you're wanting to look at.

IanB
17th February 2009, 06:44
RawSource assumes the following frame bytes layout for YV12 :-YYYY .... (width bytes)
YYYY .... (width bytes)
.... (height times)
YYYY .... (width bytes)
VV .. (width/2 bytes)
VV .. (width/2 bytes)
.. (height/2 times)
VV .. (width/2 bytes)
UU .. (width/2 bytes)
UU .. (width/2 bytes)
.. (height/2 times)
UU .. (width/2 bytes)

patrick_
17th February 2009, 08:15
Thanks kumuri-_9, but I knew that, that's why I said that it takes in account the pitch.

IanB, Thanks, but I don't know the layout of the image copied by BitBlt.

Gavino
17th February 2009, 11:12
For each frame, you should be doing 3 BitBlts and file writes, copying the data from each plane in the order Y, V, U.

For each plane, use the appropriate GetReadPtr(plane), GetPitch(plane), etc.

IanB
17th February 2009, 21:07
env->BitBlt is a very fast implementation of this :-IScriptEnvironment::BitBlt(
BYTE* dst, int dst_pitch,
BYTE* src, int src_pitch,
width, height
) {
for (y=0; y<height; y++) {
for (x=0; x<width; x++) {
dst[x] = src[x];
}
src += src_pitch;
dst += dst_pitch;
}
}So in your original code you set stride=1080 so you have copied each 720 bytes to the start of each 1080 byte group.

When you load the file back you read in 720 byte groups. Thus the byte layout is :-1 1 1 1 ... 1 1 1 1 ...
x x x x ... 2 2 2 2 ...
2 2 2 2 ... x x x x ...
3 3 3 3 ... 3 3 3 3 ...
x x x x ... 4 4 4 4 ...
4 4 4 4 ... x x x x ...
...You need to study up on in memory layouts for YV12