Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

File size - YCbCr 422 vs YCbCr 420 #93

Open
nsesh opened this issue Apr 28, 2020 · 10 comments
Open

File size - YCbCr 422 vs YCbCr 420 #93

nsesh opened this issue Apr 28, 2020 · 10 comments
Labels

Comments

@nsesh
Copy link

nsesh commented Apr 28, 2020

Hi,
Thanks for wonderful documentation.

I'm having some doubt on YCbCr 422 vs YCbCr 420 file size. As per my understanding in case of 4:2:0, the file size reduction is more than 50% compared to 4:4:4. In case of 1280x720 the alternate lines will not take Cb or Cr. Am I right?
If yes then 'Y' pixels = 1280x720x8 bits
CbCr pixels = 640x360x8 bits
Total Bytes = 1152000
Size = 115GBytes.

For 4:2:2, the alternate lines do take chroma samples and hence
Y pixels = 1280x720x8 bits
CbCr pixels = 640x720x8
Total Bytes = 139GBytes

Kindly correct me.

@leandromoreira
Copy link
Owner

leandromoreira commented Apr 29, 2020

Hi @nsesh how are you?

Let me put a summary I saw on FFmpeg docs:

  • 4:4:4: There is no chroma subsampling
  • 4:2:2: Cb' and Cr' are sampled at half the sample rate of luma, the horizontal chroma resolution is halved
  • 4:2:0: Cb' and Cr' are each subsampled at a factor of two, both horizontally and vertically

And the Wiki's drawing:

image

Both might help you to visualize the difference.

@nsesh
Copy link
Author

nsesh commented Apr 29, 2020

@leandromoreira, thanks for your reply. Yes, if you see in the diagram you shared, it is clear that for 4:2:0, both horizontal and vertical resolution are half. Hence, in my calculation the resolution for CbCr was halved i.e. 640x360. In case of 4:2:2, I kept it as 640x720.

Hence, wanted to clarify if my understanding is correct and my calculation of file is correct or not.

As per the section "Chroma Subsampling", it is mentioned 12bits for 4:2:0 and file size is mentioned half of original size. We can't just sum up the ratio's and say that file size is half of original. In fact for 4:2:0, the average bits are 10 and not 12. Hence this confusion, but please correct me if I'm still wrong :)

@leandromoreira
Copy link
Owner

It's really hard because it's conceptual, and the mapping examples given are only theoretical and for illustration.

But to calculate required bandwidth factor relative to 4:4:4, one needs to sum all the factors and divide the result by 12.

  • 4:2:0 = 6/12 = 0.5 = 50%
  • 4:2:2 = 8/12 = 0.666 = 66.66%

Let's try to put it to test.

# cut a small chunk of video
ffmpeg -i small_bunny_1080p_60fps.mp4 -t 00:00:02 2s.mp4

# Now let's generate rawvideo format with each of the proper format

ffmpeg -i 2s.mp4 -c:v rawvideo -pix_fmt yuv444p yuv444p.yuv
ffmpeg -i 2s.mp4 -c:v rawvideo -pix_fmt yuv420p yuv420p.yuv
ffmpeg -i 2s.mp4 -c:v rawvideo -pix_fmt yuv422p yuv422p.yuv

ls -lah *yuv

-rw-r--r--  1 leandro.moreira  wheel   356M Apr 28 23:19 yuv420p.yuv
-rw-r--r--  1 leandro.moreira  wheel   475M Apr 28 23:21 yuv422p.yuv
-rw-r--r--  1 leandro.moreira  wheel   712M Apr 28 23:20 yuv444p.yuv

712M = 100%
356M = 50%
475M = 66.6%

@leandromoreira
Copy link
Owner

A python view of a single frame can be seen as:

# A single frame in KB 


# full cr and cb (4:4:4)
y_plane = 1280*720*8
cr_plane = 1280*720*8
cb_plane = 1280*720*8
print((y_plane+cr_plane+cb_plane) / 8 / 1024)


# half cr and cb (4:2:0)
y_plane = 1280*720*8
cr_plane = 640*360*8
cb_plane = 640*360*8
print((y_plane+cr_plane+cb_plane) / 8 / 1024)

@leandromoreira
Copy link
Owner

image

  • 4:2:0 - For each 4 pixes in Y we have only 1 for Cb and 1 for Cr = 6 pixels ( where it should be 4+4+4)
  • 4:2:2 - For each 4 pixes in Y we have only 2 for Cb and 2 for Cr = 8 pixels (where it should be 4+4+4)

@leandromoreira
Copy link
Owner

I hope it can help you to understand @nsesh

@nsesh
Copy link
Author

nsesh commented Apr 29, 2020

@leandromoreira, thanks so much. The above pic and python view of single frame help me to understand the mistake I did.

For 4:2:0
'Y' pixels = 1280x720x8 bits
CbCr pixels = 640x360x8 bits + 640x360x8 bits
Total Bytes = 139GBytes (~50%)

For 4:2:2
Y pixels = 1280x720x8 bits
CbCr pixels = 640x720x8 bits + 640x720x8 bits
Total Bytes = 185GBytes (~66%)

Once again thanks very much for clearly explaining.

@nsesh nsesh closed this as completed Apr 29, 2020
@nsesh nsesh reopened this Apr 29, 2020
@nsesh
Copy link
Author

nsesh commented Apr 29, 2020

@leandromoreira, just want to understand on 4:1:1

Y pixels = 1280x720x8 bits
CbCr pixels = 320x720x8 bits + 320x720x8 bits
Total Bytes = 139GBytes (50%).

Is my understanding correct?

If you can get the similar picture as explained above that will be helpful.

@nsesh
Copy link
Author

nsesh commented Apr 29, 2020

Screenshot 2020-04-29 at 9 26 32 AM

got understanding from above diagram and hence closing this issue. Once again thanks very much.

@nsesh nsesh closed this as completed Apr 29, 2020
@leandromoreira
Copy link
Owner

I'll leave this open as it can help other people!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants