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.

 

Go Back   Doom9's Forum > Capturing and Editing Video > Avisynth Development

Reply
 
Thread Tools Search this Thread Display Modes
Old 1st July 2011, 12:52   #21  |  Link
pandy
Registered User
 
Join Date: Mar 2006
Posts: 1,038
Thank You Very Much! - IMO MPEG-2 is kind of standard (even if MPEG-1 position is IMHO better) - H.264 use MPEG-2 chroma sample location
pandy is offline   Reply With Quote
Old 1st July 2011, 13:16   #22  |  Link
xv
Registered User
 
Join Date: Mar 2010
Posts: 98
Thatīs why I used MPEG-2 chroma position (in fact H.264 supports many chroma positions, there is a bitstream flag, but probably all decoder/renderer ignore that)

Iīm not sure I did it correct with src_left=-0.5
xv is offline   Reply With Quote
Old 1st July 2011, 15:06   #23  |  Link
Gavino
Avisynth language lover
 
Join Date: Dec 2007
Location: Spain
Posts: 3,380
Quote:
Originally Posted by xv View Post
Iīve added support for YUY2 and YV12 subsampling. Iīve done this by calling lanczos to resize U/V plane.
Iīm not sure thatīs correct, but I used src_left=-0.5 for YV12 to have correct chroma position, does anyone know if thatīs correct?
src_left=-0.5 for downsizing and src_left=+0.25 for upsizing
__________________
GScript and GRunT - complex Avisynth scripting made easier
Gavino is offline   Reply With Quote
Old 1st July 2011, 15:16   #24  |  Link
xv
Registered User
 
Join Date: Mar 2010
Posts: 98
Quote:
Originally Posted by Gavino View Post
src_left=-0.5 for downsizing and src_left=+0.25 for upsizing
Thanks, so I did it correct
Is lanczos recommend for Chroma downsizing? Iīve seen jmac698 used BilinearResize for downsizing in his script.
xv is offline   Reply With Quote
Old 1st July 2011, 15:43   #25  |  Link
Gavino
Avisynth language lover
 
Join Date: Dec 2007
Location: Spain
Posts: 3,380
Internally Avisynth uses (the equivalent of) BilinearResize for the default conversion path, and when using the chromaresample option of v2.60, the default is bicubic.
__________________
GScript and GRunT - complex Avisynth scripting made easier
Gavino is offline   Reply With Quote
Old 13th January 2012, 06:18   #26  |  Link
Zerofool
VR, 3D & HDR UHD fan
 
Join Date: Mar 2006
Location: Sofia, Bulgaria
Posts: 53
Hello,

I recently found out about this colorspace and the possible compression gains so I decided to give it a try with x264.

My source is fullrange RGB. Unfortunately, the resulting file doesn't look exactly right, the black level is off (should be 0/0/0 but it's 0/19/18) and the video is blue-ish. Pure white is OK though (255/255/255). I use the latest MadVR as both decoder and renderer (through MPC-HC), and also tried LAVF+MadVR with the same success. My encoding settings include:
Code:
--colormatrix YCgCo --range pc --input-range pc --output-csp i444
and I tried with both the 10-bit and 8-bit x264 builds.

I noticed that you said this:
Quote:
Originally Posted by xv View Post
x264 for example accepts YV24 and can encode it correctly (with --colormatrix YCgCo --fullrange on).
Is that for limited-range sources? If so, how does your filter treat full-range sources?

Is there anything that I can do to correct the situation? Should any special --colorprim and --transfer parameters be set when encoding? Because MadVR says "primaries BT.709 (says bitstream)".

Anyway, if I use any other renderer the black is OK (and all the grayscale as a whole), but naturally, the colors are messed up .

Your BigBuckBunny samples look OK through MadVR (dec+rend) though...
Zerofool is offline   Reply With Quote
Old 13th January 2012, 07:00   #27  |  Link
Zerofool
VR, 3D & HDR UHD fan
 
Join Date: Mar 2006
Location: Sofia, Bulgaria
Posts: 53
Nope, not exactly sure, just suspecting it does. There's nothing about YCgCo in madVR's changelog, so nothing official. I could only find this statement of the author:

Quote:
Originally Posted by madshi View Post
Also keep in mind that h264 allows more matrices to be used, e.g. YCgCo, GBR, SMPTE 240M. I have h264 samples which were encoded with YCgCo and GBR matrices. And madVR v0.69 now treats them correctly (automatically).
Truth to be told, with madVR the video looks close to what I expect it to look like, so it's some minor glitch, but I don't know if it's in the renderer, this filter, or in my encoding approach.
The samples I mentioned (probably the ones madshi talks about) look normal, as far as I can tell.

Last edited by Zerofool; 13th January 2012 at 07:05.
Zerofool is offline   Reply With Quote
Old 4th March 2012, 00:17   #28  |  Link
xv
Registered User
 
Join Date: Mar 2010
Posts: 98
It seems that the problem is somewhere in madVR. I made a few samples and noticed similar problems. But madVR is not open-source so I cannot analyze the problem, madshi has to do that.

To verify that your encoding is correct open the file in avisynth and add the following command (you need the ManualColorMatrix plug-in):
Code:
ManualColorMatrix(2, 1.0, -1.0, 1.0, 1.0, 1.0, 0.0, 1.0, -1.0, -1.0, 0.0, -128.0, 256.0)
This will convert YCgCo manually to RGB (you need AviSynth 2.6 for YV24 support). If colors are wrong something is wrong with your encode, otherwise the problem is madVR.
xv is offline   Reply With Quote
Old 11th March 2012, 23:15   #29  |  Link
xv
Registered User
 
Join Date: Mar 2010
Posts: 98
Madshi has fixed YCgCo matrix in madVR 0.82.5!
Now correctly encoded videos should look perfect.
xv is offline   Reply With Quote
Old 12th March 2012, 19:17   #30  |  Link
LexSfX
Registered User
 
Join Date: Feb 2012
Posts: 36
Hi, XV. I am posting this on behalf of natt, a proficient video encoder from tasvideos.org. He wrote the following in response to your colorspace conversion code.

---

(Note: I'm working off the 2011 h.264 spec)

The h.264 spec is very explicit about how RGB->YCgCo should be rounded. Looking over your source code (the C++ version), it doesn't appear to follow those conventions. In particular, rounding should be done towards the nearest integer (not towards zero).

As a part of a little educational study, I wrote an RGB->YCgCo converter a while back, and I believe it fully implements the conversion with rounding exactly as the specification requires. (Of course, if there's any disagreement, I'd love to see test vectors).

It's in C, and also implements the case of different bitdepths between RGB and YCgCo (which is not needed here) by changing BITDEPTHR and BITDEPTHY.

Code:
typedef struct
{
  int y;
  int cg; // "Cb"
  int co; // "Cr"
} ycc_t;

typedef struct
{
  int r;
  int g;
  int b;
} rgb_t;

// R,G,B have bitdepth BITDEPTHR
// Y,Cg,Co have bitdepth BITDEPTHY

#define BITDEPTHR 8
#define BITDEPTHY 8

#define SRCRNG ((1 << BITDEPTHR) - 1) // rgb values are from [0, SRCRNG]

#define SFC (1 << (BITDEPTHY - 1)) // used in some calculations, the "center point" of Cg, Co
#define RNG ((1 << BITDEPTHY) - 1) // ycc values are from [0, RNG]



void rgb_to_ycgco_int (ycc_t *dst, const rgb_t *src)
{ // E-19 through E-21
  int r = src->r * RNG;
  int g = src->g * RNG;
  int b = src->b * RNG;

  int  y = 2 * g + r + b;
  int cb = 2 * g - r - b;
  int cr = 2 * r - 2 * b;
  
  // round away from 0
  y += 2 * SRCRNG;
  if (cb < 0)
    cb -= 2 * SRCRNG;
  else
    cb += 2 * SRCRNG;
  if (cr < 0)
    cr -= 2 * SRCRNG;
  else
    cr += 2 * SRCRNG;
  
  y /= 4 * SRCRNG;
  cb /= 4 * SRCRNG;
  cr /= 4 * SRCRNG;
  cb += SFC;
  cr += SFC;

  // clip
  if (cb > RNG)
    cb--;
  if (cr > RNG)
    cr--;
    
  dst->y = y;
  dst->cg = cb;
  dst->co = cr;
  
}
-natt
LexSfX is offline   Reply With Quote
Old 12th March 2012, 23:15   #31  |  Link
xv
Registered User
 
Join Date: Mar 2010
Posts: 98
You are right. How rounding is done in C++ version is defined by compiler, which is not good. SSE2 version was wrong (rounding towards zero). Fixing is really simple, I just added 0.5 and then use floor() to ensure itīs rounded towards zero (this is also what H.264 spec says). In SSE2 I just changed cvttps2dq to cvtps2dq.
Could you verify itīs correct?
Only using integers for conversion is interesting and is most likely also a lot faster. When I find some time Iīll rewrite my assembly integer-only and see how it compares in speed. Results should be the same.
Attached Files
File Type: zip ConvertToYCgCo_v03.zip (50.4 KB, 24 views)
xv is offline   Reply With Quote
Old 15th March 2012, 01:04   #32  |  Link
xv
Registered User
 
Join Date: Mar 2010
Posts: 98
ConvertToYCgCo v0.4 released

I converted all code to int-only. Output of C and SSE version is bit-identical (as it should be) and should conform to H.264 spec. Using ints instead of float also gives a speed increase (especially for the C version).
I used binary operations instead of arithmetic to increase performance, thatīs the way Iīve done it:
Code:
g<<=1; // the same as g*=2;
y = g+r+b;
cg = g-r-b+512;
co = r-b+256;
if (y&0x2) { y>>=2; y++; } // same as if(y%4>1) { y/=4; y++; }
else y>>=2;
if (cg&0x2) { cg>>=2; cg++; if(cg>255) cg--; }
else cg>>=2;
if (co&0x1) { co>>=1; co++; if(co>255) co--; }
else co>>=1;
Please check if everything is 100% correct now.
Attached Files
File Type: zip ConvertToYCgCo_v04.zip (50.2 KB, 334 views)
xv is offline   Reply With Quote
Old 19th March 2012, 01:11   #33  |  Link
natt
Registered User
 
Join Date: Mar 2012
Posts: 10
Sorry for the slow response time. I had to wait for the board-imposed 5 day timeout, and didn't want to make Lex carry around messages for me.

The idea looks basically right, except for one hitch: the rounding for Cg, Co. The h264 spec says that you're supposed to round before you add 128:

Quote:
Y = Round( 0.5 * G + 0.25 * ( R + B ) )
Cg = Round( 0.5 * G − 0.25 * ( R + B ) ) + 128
Co = Round( 0.5 * (R − B ) ) + 128
So your rounding of Y is correct, and Cg and Co when they're in [128,255] ([0, 127] before +128). But the rounding tricks don't work right with negatives unless you make a second case. For instance:

Round ( (-75) / 2)

As in the h264 spec:
Round (-37.5)
Sign(-37.5)*Floor(Abs(-37.5) + 0.5)
(-1)*Floor(38)
-38

Truncate and then add 1 because the original was odd:
(-75) / 2 + 1
(-37) + 1
-36
natt is offline   Reply With Quote
Old 19th March 2012, 20:20   #34  |  Link
xv
Registered User
 
Join Date: Mar 2010
Posts: 98
Also your example is wrong you are right:

The problem is Iīve not seen the 0.5 problem. My code rounds up, but spec says in this case round away from zero, and that of course makes a difference for negative numbers. For .25 and .75 rounding is correct:
Code:
Round((-75)/2) + 128 = Sign(-37.5)*Floor(Abs(-37.5)+0.5) + 128 = (-1)*Floor(38) + 128 = -38 + 128 = 90
(-75 + 256) / 2 = 181/2 = 90 + 1 = 91  => NOT OK

Round((-149)/4) + 128 = Sign(-37.25)*Floor(Abs(-37.25)+0.5) + 128 = (-1)*Floor(37.75) + 128 = -37 + 128 = 91
(-149 + 512) / 4 = 363/4 = 90 + 1 = 91  => OK

Round((-151)/4) + 128 = Sign(-37.75)*Floor(Abs(-37.75)+0.5) + 128 = (-1)*Floor(38.25) + 128 = -38 + 128 = 90
(-151 + 512) / 4 = 361/4 = 90 + 0 = 90  => OK
Iīll see how I can fix that efficiently.
xv is offline   Reply With Quote
Old 24th March 2012, 15:24   #35  |  Link
aufkrawall
Registered User
 
Join Date: Dec 2011
Posts: 1,702
Quote:
Originally Posted by xv View Post
Iīll see how I can fix that efficiently.
When you have fixed it, converting RGB to I444 YCgCo should be totally lossless, right?
That would be really very cool, makes RGB redundant.

Edit: Is there any way to losslessly convert back to RGB?

Last edited by aufkrawall; 24th March 2012 at 20:10.
aufkrawall is offline   Reply With Quote
Old 25th March 2012, 01:41   #36  |  Link
natt
Registered User
 
Join Date: Mar 2012
Posts: 10
Quote:
Originally Posted by aufkrawall View Post
When you have fixed it, converting RGB to I444 YCgCo should be totally lossless, right?
That would be really very cool, makes RGB redundant.

Edit: Is there any way to losslessly convert back to RGB?
You need at least one more bit, ie, RGB 8bit->YCgCo 9bit->RGB 8bit is perfect. There's no way to exactly express every value from RGB 8bit in YCgCo 8bit because YCgCo covers a lot more colors.
natt is offline   Reply With Quote
Old 25th March 2012, 13:36   #37  |  Link
aufkrawall
Registered User
 
Join Date: Dec 2011
Posts: 1,702
Quote:
Originally Posted by natt View Post
You need at least one more bit, ie, RGB 8bit->YCgCo 9bit->RGB 8bit is perfect. There's no way to exactly express every value from RGB 8bit in YCgCo 8bit because YCgCo covers a lot more colors.
Can this be achieved with the 10 bit version of x264?
aufkrawall is offline   Reply With Quote
Old 25th March 2012, 19:25   #38  |  Link
Zerofool
VR, 3D & HDR UHD fan
 
Join Date: Mar 2006
Location: Sofia, Bulgaria
Posts: 53
Quote:
Originally Posted by xv View Post
Madshi has fixed YCgCo matrix in madVR 0.82.5!
Now correctly encoded videos should look perfect.
I had deleted my previous test samples, so I redid the tests with your latest plug-in (v04), and yes, they all work perfectly with the latest madVR version. Thanks for the heads up!
Unfortunately, I didn't see the expected compression efficiency improvement, only few tens of kilobytes with the little testing I did, but there are possibly cases where the difference will be bigger.

Quote:
Originally Posted by xv View Post
To verify that your encoding is correct open the file in avisynth and add the following command (you need the ManualColorMatrix plug-in):
Code:
ManualColorMatrix(2, 1.0, -1.0, 1.0, 1.0, 1.0, 0.0, 1.0, -1.0, -1.0, 0.0, -128.0, 256.0)
This will convert YCgCo manually to RGB (you need AviSynth 2.6 for YV24 support). If colors are wrong something is wrong with your encode, otherwise the problem is madVR.
Unfortunately, I don't know how to do that, because all H.264 decoders that support 4:4:4 decoding (to my knowledge), only support AYUV output colorspace, which is the closest to YV24, but Avisynth obviously doesn't like it at all. Any suggestions in that regard are welcome.

Quote:
Originally Posted by aufkrawall View Post
Can this be achieved with the 10 bit version of x264?
That's what I wondered and asked Dark Shikari, but received no answer, most likely meaning it won't work, or it's too much trouble to implement:
Quote:
Originally Posted by Zerofool View Post
Let's say we have a 8bpp RGB clip, so for its conversion we'll need at least 8bit luma and at least 9bit chroma. So what if we do the conversion and then we upscale the result to 10bit? That way both luma and chroma will have the same depth. Wouldn't the color values remain the same and therefore reproduce the initial 8bpp RGB in the end? Wouldn't it work that way?

Last edited by Zerofool; 25th March 2012 at 19:40.
Zerofool is offline   Reply With Quote
Old 25th March 2012, 22:22   #39  |  Link
natt
Registered User
 
Join Date: Mar 2012
Posts: 10
Quote:
Originally Posted by aufkrawall View Post
Can this be achieved with the 10 bit version of x264?
When you tell x264 "--colormatrix YCgCo", all it does set the VUI flag. It otherwise completely ignores it.

That means that if you send x264 supposed "YUV" data that is in fact YCgCo, it will pass it through unmolested, compress it appropriately, and set the VUI flag for YCgCo.

How you do that depends on your workflow. This plugin will allow it with 8 bit, and will work if x264 reads the script directly or you use something like avs2pipemod.

For 10 bit, I don't personally know much about how high bitdepth inside avisynth works. What I did for a few test clips is have my script output the original BGR, and then use a simple command line application of my own creation to do BGR 8 8 8->YCgCo 10 10 10. Seemed to work fine (but was affected by the madvr "teal bug" at the time).
natt is offline   Reply With Quote
Old 26th March 2012, 02:33   #40  |  Link
aufkrawall
Registered User
 
Join Date: Dec 2011
Posts: 1,702
Quote:
Originally Posted by natt View Post
When you tell x264 "--colormatrix YCgCo", all it does set the VUI flag. It otherwise completely ignores it.

That means that if you send x264 supposed "YUV" data that is in fact YCgCo, it will pass it through unmolested, compress it appropriately, and set the VUI flag for YCgCo.

How you do that depends on your workflow. This plugin will allow it with 8 bit, and will work if x264 reads the script directly or you use something like avs2pipemod.
That sounds good.

Quote:
Originally Posted by natt View Post
For 10 bit, I don't personally know much about how high bitdepth inside avisynth works. What I did for a few test clips is have my script output the original BGR, and then use a simple command line application of my own creation to do BGR 8 8 8->YCgCo 10 10 10. Seemed to work fine (but was affected by the madvr "teal bug" at the time).
Please, how would you convert a YCgCo 8 bit video back to RGB without writing an own helper tool for this?
When I tell Avisynth or x264 to simply convert to RGB, the result is a mess of colors.

Edit: The plug in would need to convert back to RGB, I suppose.

Last edited by aufkrawall; 27th March 2012 at 18:34.
aufkrawall is offline   Reply With Quote
Reply

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +1. The time now is 23:34.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2018, vBulletin Solutions Inc.