Welcome to Doom9's Forum, THE in-place to be for everyone interested in DVD conversion. Before you start posting please read the forum rules. By posting to this forum you agree to abide by the rules. |
28th March 2010, 02:38 | #1 | Link |
Registered User
Join Date: Feb 2010
Location: Russia
Posts: 21
|
r,g,b in YV12
Work in YU12 colorspace.
plane=PLANAR_Y; pFrame1 = frame1->GetReadPtr(plane); //prosessing pOut_frame = out_frame->GetWritePtr(plane); plane=PLANAR_U; pFrame1 = frame1->GetReadPtr(plane); //prosessing pOut_frame = out_frame->GetWritePtr(plane); plane=PLANAR_V; pFrame1 = frame1->GetReadPtr(plane); //prosessing pOut_frame = out_frame->GetWritePtr(plane); When prosessing with Y (plane=PLANAR_Y), i may recieve variable Y of each pixel (*pOut_frame=*pFrame1) . When I may recieve variables V,U in this cycle? http://en.wikipedia.org/wiki/YUV said, that Y=*pFrame1; pFrame1+=((height*width)+(height*width)/4); V=*pFrame1; pFrame1-=((height*width)+(height*width)/4); R=(BYTE)(Y+(1.13983*V)); R=*pFrame1; *pOut_frame=R; But it isn't working. Why? How i assign *pOut_frame=R? |
28th March 2010, 09:55 | #2 | Link |
Avisynth Developer
Join Date: Jan 2003
Location: Melbourne, Australia
Posts: 3,167
|
You cannot assume the in memory layout of PVideoFrames.
You must ask the API for pointers to the start of each plane and the line pitch for that plane in order to access the require pixel. Install the FilterSDK when you install Avisynth, this will give you a lot of examples and documentation. Fizick, who does a lot of work on the SDK doco also maintains a Russian Avisynth site that you may find helpful. For YV12 and RGB32 :- Code:
pFrame1Y = frame1->GetReadPtr(PLANAR_Y); pFrame1U = frame1->GetReadPtr(PLANAR_U); pFrame1V = frame1->GetReadPtr(PLANAR_V); pOut_frame = out_frame->GetWritePtr(); pitchY = frame1->GetPitch(PLANAR_Y); pitchU = frame1->GetPitch(PLANAR_U); pitchV = frame1->GetPitch(PLANAR_V); outPitch = out_frame->GetPitch(); ... Y=pFrame1Y[x+y*pitchY]; V=pFrame1V[x/2+y/2*pitchV]; R=(BYTE)(Y+(1.13983*V)); ... // RGB32 is upside down. pOut_frame[x*4+(height-y-1)*outPitch+3]=0; // Alpha pOut_frame[x*4+(height-y-1)*outPitch+2]=R; pOut_frame[x*4+(height-y-1)*outPitch+1]=G; pOut_frame[x*4+(height-y-1)*outPitch+0]=B; |
30th March 2010, 13:55 | #5 | Link |
Registered User
Join Date: Feb 2010
Location: Russia
Posts: 21
|
Code:
pFrame2 = frame2->GetReadPtr(PLANAR_Y); pFrame2U = frame2->GetReadPtr(PLANAR_U); pFrame2V = frame2->GetReadPtr(PLANAR_V); pOut_frame = out_frame->GetWritePtr(); frame_pitch = frame1->GetPitch(PLANAR_Y); frame_pitchU = frame1->GetPitch(PLANAR_U); ..... //Frame divide on blocks. Every Block read and write. //pFrame2 - poiner on begin block (0,0), Y //pFrame2U - poiner on begin block (0,0), U //pFrame2V - poiner on begin block (0,0), V .... for(int i=0;i<s_block;i++) { for(int j=0;j<s_block;j++) { if(j!=0) { pOut_frame+=1; pFrame2+=1; pFrame2U+=1; pFrame2V+=1; } Y=*pFrame2; U=*pFrame2U; V=*pFrame2V; G=(BYTE)(Y-(0.39465*U)-(0.58060*V)); *pOut_frame=G; } pFrame2+=(-(s_block-1)+frame_pitch); pFrame2U+=(-(s_block-1)+frame_pitchU); pFrame2V+=(-(s_block-1)+frame_pitchU); pOut_frame+=(-(s_block-1)+frame_pitch); } If I write U - (*pOut_frame=U), I recieve bad frame: If I write V - (*pOut_frame=V), I recieve frame divided into 4 small frames of normal frame: Where is the error? Last edited by slicktail; 30th March 2010 at 17:27. |
30th March 2010, 21:45 | #7 | Link |
Avisynth Developer
Join Date: Jan 2003
Location: Melbourne, Australia
Posts: 3,167
|
Yes 2x2 Y pixels for 1x1 U and V pixels, also every frame and every plane has its own pitch value.
You mention frame1, frame2 and out_frame in your code fragment yet you use frame1's pitch with frame2 and out_frame. You will need to tell us about the code to get more specific help. Look how SimpleSample in the SDK documentation changes as each improvement adds a new colour space or feature. See 1.1 and 1.6 for adding YV12. |
31st March 2010, 16:13 | #8 | Link |
Registered User
Join Date: Feb 2010
Location: Russia
Posts: 21
|
Each Frame divided on blocks size (s_block*s_block)
Then find move (SAD) When I output frame, i want converted Y - R, etc Code:
for(int i=0;i<s_block;i++) { for(int j=0;j<s_block;j++) { if(j!=0) { pOut_frame+=1; pFrame2+=1; pFrameX+=1; } //there must be converted to R *pOut_frame=(BYTE)(*pFrameX+(*pFrame2-*pFrameX)*t); } pFrame2+=(-(s_block-1)+frame_pitch); pFrameX+=(-(s_block-1)+frame_pitch); pOut_frame+=(-(s_block-1)+frame_pitch); } There is full code: Block.rar |
1st April 2010, 00:10 | #9 | Link |
Avisynth Developer
Join Date: Jan 2003
Location: Melbourne, Australia
Posts: 3,167
|
As I keep saying, with Pitch you must use the value that goes with each PVideoFrame instance. As soon as someone does a SeparateFields(), a Crop() or a Splice() in the script then the values will be different for different frames. You only get frame1 pitch, yet you try to use it with frame2 and out_frame.
And you must account for the chroma planes being half height and half width. e.g. Line 0 Y[0,0], U[0,0], V[0,0] Y[1,0], U[0,0], V[0,0] Y[2,0], U[1,0], V[1,0] Y[3,0], U[1,0], V[1,0] Y[4,0], U[2,0], V[2,0] ... Line 1 Y[0,1], U[0,0], V[0,0] Y[1,1], U[0,0], V[0,0] Y[2,1], U[1,0], V[1,0] Y[3,1], U[1,0], V[1,0] Y[4,1], U[2,0], V[2,0] ... Line 2 Y[0,2], U[0,1], V[0,1] ... |
6th April 2010, 05:46 | #11 | Link |
Registered User
Join Date: Feb 2010
Location: Russia
Posts: 21
|
Code:
PVideoFrame frame1 = child->GetFrame(n, env); PVideoFrame out_frame = env->NewVideoFrame(vi); pFrame1 = frame1->GetReadPtr(PLANAR_Y); pFrame1U = frame1->GetReadPtr(PLANAR_U); width = out_frame->GetRowSize(); height = out_frame->GetHeight(); pOut_frame = out_frame->GetWritePtr(); for (int h=0;h<height*width;h++) { Y=pFrame1[h]; //U=pFrame1U[h]; pOut_frame[h]=Y; } return out_frame; |
6th April 2010, 08:47 | #12 | Link |
Avisynth Developer
Join Date: Jan 2003
Location: Melbourne, Australia
Posts: 3,167
|
Assuming your input is YV12 and your output is to be RGB32, then here is a (slowish) YV12 to RGB32 template.
Code:
// Rec601 coefficients // =================== #define Kr 0.299 #define Kg 0.587 #define Kb 0.114 // YUV to RGB conversion constants // =============================== const int crv = int(2*(1-Kr) * 255.0/224.0 * 65536+0.5); const int cgv = int(2*(1-Kr)*Kr/Kg * 255.0/224.0 * 65536+0.5); const int cgu = int(2*(1-Kb)*Kb/Kg * 255.0/224.0 * 65536+0.5); const int cbu = int(2*(1-Kb) * 255.0/224.0 * 65536+0.5); // Inline helper methods static __inline BYTE ScaledPixelClip(int i) { const int x = (i+32768) >> 16; if (x <= 0) return 0; if (x >= 255) return 255; return (BYTE)x; } //=========================================== PVideoFrame frame1 = child->GetFrame(n, env); // Assumed to be YV12 BYTE *pFrame1Y = frame1->GetReadPtr(PLANAR_Y); BYTE *pFrame1U = frame1->GetReadPtr(PLANAR_U); BYTE *pFrame1V = frame1->GetReadPtr(PLANAR_V); const int pitchY = frame1->GetPitch(PLANAR_Y); const int pitchU = frame1->GetPitch(PLANAR_U); const int pitchV = frame1->GetPitch(PLANAR_V); PVideoFrame out_frame = env->NewVideoFrame(vi); // Assumed to be RGB32 BYTE *pOut_frame = out_frame->GetWritePtr(); const int outPitch = out_frame->GetPitch(); const int height = vi.height; const int width = vi.width; pOut_frame += outPitch*height; // RGB is upside down for (int h=0; h<height; h++) { pOut_frame -= outPitch; for (int w=0; w<width; w++) { const int Y = (pFrame1Y[w]-16) * int(255.0/219.0*65536+0.5); const int U = pFrame1U[w/2]-128; const int V = pFrame1V[w/2]-128; pOut_frame[w*4+0] = ScaledPixelClip(Y + U * cbu ); // Blue pOut_frame[w*4+1] = ScaledPixelClip(Y - U * cgu - V * cgv); // Green pOut_frame[w*4+2] = ScaledPixelClip(Y + V * crv); // Red pOut_frame[w*4+3] = 0; // Alpha } if (h & 1) { // Only every 2nd line pFrame1U += pitchU; pFrame1V += pitchV; } pFrame1Y += pitchY; } return out_frame; The above is by no means the fastest way, but I hope the steps are more clear as it is written. Possible improvements are to do 2 lines per outer loop and 2 pixels per inner loop, i.e. reference and calculate the U and V values once only for processing with 4 Y pixels. |
6th April 2010, 09:35 | #13 | Link |
Registered User
Join Date: Feb 2010
Location: Russia
Posts: 21
|
IanB, thank you. Your code is very useful!
But: Input frame - YV12 If I use BYTE *pOut_frame = out_frame->GetWritePtr(), output frame will be in YV12 or RGB? Please, write, how may in one cycle use Y,U,V in YV12 output frame (such as SimpleSample 1.6,but in SimpleSample is three cycle). IanB, sorry for my nub. |
6th April 2010, 10:57 | #14 | Link | ||
Avisynth language lover
Join Date: Dec 2007
Location: Spain
Posts: 3,431
|
Quote:
If you want it to be different, you have to change the appropriate vi property in your constructor, eg vi.pixel_type = CS_BGR32; Quote:
|
||
6th April 2010, 16:11 | #15 | Link | |
Registered User
Join Date: Feb 2010
Location: Russia
Posts: 21
|
Quote:
|
|
6th April 2010, 22:49 | #16 | Link |
Avisynth language lover
Join Date: Dec 2007
Location: Spain
Posts: 3,431
|
Basically, something like this:
Code:
PVideoFrame frame1 = child->GetFrame(n, env); // Assumed to be YV12 BYTE *pFrame1Y = frame1->GetReadPtr(PLANAR_Y); BYTE *pFrame1U = frame1->GetReadPtr(PLANAR_U); BYTE *pFrame1V = frame1->GetReadPtr(PLANAR_V); const int pitchY = frame1->GetPitch(PLANAR_Y); const int pitchU = frame1->GetPitch(PLANAR_U); const int pitchV = frame1->GetPitch(PLANAR_V); PVideoFrame out_frame = env->NewVideoFrame(vi); // Assumed to be YV12 also BYTE *pOut_frameY = out_frame->GetWritePtr(PLANAR_Y); BYTE *pOut_frameU = out_frame->GetWritePtr(PLANAR_U); BYTE *pOut_frameV = out_frame->GetWritePtr(PLANAR_V); const int outPitchY = out_frame->GetPitch(PLANAR_Y); const int outPitchU = out_frame->GetPitch(PLANAR_U); const int outPitchV = out_frame->GetPitch(PLANAR_V); const int height = vi.height; const int width = vi.width; for (int h=0; h<height; h++) { for (int w=0; w<width; w++) { const int Y = pFrame1Y[w]; const int U = pFrame1U[w/2]; const int V = pFrame1V[w/2]; ... // calculate output Y, U, V values pOut_frameY[w] = ... ; // write output Y pOut_frameU[w/2] = ... ; // U pOut_frameV[w/2] = ... ; // V } if (h & 1) { // Only every 2nd line pFrame1U += pitchU; pFrame1V += pitchV; pOut_frameU += outPitchU; pOut_frameV += outPitchV; } pFrame1Y += pitchY; pOut_frameY += outPitchY; } return out_frame; |
6th April 2010, 23:45 | #17 | Link |
Avisynth Developer
Join Date: Jan 2003
Location: Melbourne, Australia
Posts: 3,167
|
Snap Gavino
Of course when outputting YV12 you need accumulate the final U and V values over source 4 pixels, hence you need to process 4 pixels per iteration. Here is a template to apply an arbitrary per pixel transform. Code:
BYTE FunctionY(int Y, int U, int V); int FunctionU(int Y, int U, int V); int FunctionV(int Y, int U, int V); // ========================================== PVideoFrame frame1 = child->GetFrame(n, env); // Assumed to be YV12 BYTE *pFrame1Y = frame1->GetReadPtr(PLANAR_Y); BYTE *pFrame1U = frame1->GetReadPtr(PLANAR_U); BYTE *pFrame1V = frame1->GetReadPtr(PLANAR_V); const int pitchY = frame1->GetPitch(PLANAR_Y); const int pitchU = frame1->GetPitch(PLANAR_U); const int pitchV = frame1->GetPitch(PLANAR_V); PVideoFrame out_frame = env->NewVideoFrame(vi); // Assumed to be YV12 BYTE *pOut_frameY = out_frame->GetWritePtr(PLANAR_Y); BYTE *pOut_frameU = out_frame->GetWritePtr(PLANAR_U); BYTE *pOut_frameV = out_frame->GetWritePtr(PLANAR_V); const int outPitchY = out_frame->GetPitch(PLANAR_Y); const int outPitchU = out_frame->GetPitch(PLANAR_U); const int outPitchV = out_frame->GetPitch(PLANAR_V); const int height = vi.height; const int width = vi.width; BYTE *pFrame1Y1 = pFrame1Y + pitchY; BYTE *pOut_frameY1 = pOut_frameY + outPitchY; for (int h=0; h<height; h+=2) { // Only every 2nd line for (int w=0; w<width; w+=2) { // Only every 2nd pixel int Y, outU, outV; const int U = (pFrame1U[w/2] - 128) * int(255.0/112.0*65536+0.5); const int V = (pFrame1V[w/2] - 128) * int(255.0/112.0*65536+0.5); // Pixel[00] Y = (pFrame1Y[w]-16) * int(255.0/219.0*65536+0.5); pOut_frameY[w] = FunctionY(Y, U, V); outU = FunctionU(Y, U, V); outV = FunctionV(Y, U, V); // Pixel[01] Y = (pFrame1Y[w+1]-16) * int(255.0/219.0*65536+0.5); pOut_frameY[w+1] = FunctionY(Y, U, V); outU += FunctionU(Y, U, V); outV += FunctionV(Y, U, V); // Pixel[10] Y = (pFrame1Y1[w]-16) * int(255.0/219.0*65536+0.5); pOut_frameY1[w] = FunctionY(Y, U, V); outU += FunctionU(Y, U, V); outV += FunctionV(Y, U, V); // Pixel[11] Y = (pFrame1Y1[w+1]-16) * int(255.0/219.0*65536+0.5); pOut_frameY1[w+1] = FunctionY(Y, U, V); outU += FunctionU(Y, U, V); outV += FunctionV(Y, U, V); // (Pixel[00]+Pixel[01]+Pixel[10]+Pixel[11]+2)/4 pOut_frameU[w/2] = BYTE((outU + 2 + 128*4) / 4); pOut_frameV[w/2] = BYTE((outV + 2 + 128*4) / 4); } pFrame1Y += pitchY*2; pFrame1Y1 += pitchY*2; pFrame1U += pitchU; pFrame1V += pitchV; pOut_frameY += outPitchY*2; pOut_frameY1 += outPitchY*2; pOut_frameU += outPitchU; pOut_frameV += outPitchV; } return out_frame; Last edited by IanB; 17th April 2010 at 08:08. Reason: Ah Damn! Snap Gavino + GetWritePtr :o |
|
|