mpv-player / mpv

🎥 Command line video player
https://mpv.io
Other
28.14k stars 2.89k forks source link

optional feature suggestion: video scaling at only to integer scales. #10097

Closed rezad1393 closed 2 years ago

rezad1393 commented 2 years ago

I have recently been ocupied by issues with linux and zoom scales and wayland stuff.

one thing that bothers me is that in wayland right now if I set global scale to 150% then my screen becomes a lower resolution screen, unlike X11 that just scales up the application with paramateres. so in wayland in this situation if I view a 1080 picture in its actual scale it would spill out of screen.

because wayland would give a 720p virtual screen to the picture viewer and then my desktop (or wayland itself, I am not that familiar with it) would paint that 720p result picture on screen? so twice the non-integer scaling and so twice the quality degradation, if I am right.

as I reported here: https://bugs.kde.org/show_bug.cgi?id=452261

now that is a non-mpv and separate issue but that made me think about the way mov would paint a picture on physical screen (any screen, windows or linux or anything)

I have a 1080p screen. because pictures (form movies) are not vector but actual pixels so they cant be easily mapped to screen. so when the scale is not integer of each other ,unlike a 540p movie shown on a 1080p, then any program that tries to paint them on screen has to approximate groups pixel from picture to pixels on screen that is not one but one.

I have seen this even with my own eyes when in a 1080p movie a character has a clothe that has many parallel lines in its clothes that on full screen are shown nicely but when I make the mpv window small (like a 500p then those line gets wavy and and non-parallel and blend together very badly.

something like that (like anti-aliasing) happens for movies that are zoomed out at non-integer scale.

this is not a codec thing (I think) , it is just the result of mpv ,or any thing in its pipeline to show on screen that has to at the end show a pixel on the physical screen and doesn't have 1 to 1 match.

so for sure this causes quality degradation (any thing that changes the end result pixel not be the best match of source) now for movies with pixels higher than my screen there is not much else to do. but for movies that are smaller I have a suggestion for an optional setting that the movies be scaled up in integer numbers that at the end any pixel from picture result in crisp picture on screen.

right now move just kinda stretches the picture until either length or height get to the edges of its window (or at least in full screen mode the edges of screen) and this is a fractional scaling that will make the movie not be shown exactly like the source.

but if my suggestion can be implemented as an option (or maybe a script) then a 480p movie that is 720x480 on my screen in full screen would be shown in my screen at a 1440x960 and not 1620x1080.

this is not a UI or security bug, but I think for a program that its main job is showing a picture then image fidelity is important.

this is a picture that I could find fast on internet. one is the screenshot of the image as shown on my screen when in natural size (one to one match to physical screen) the other in zoomed in and screenshot.

if you zoom out the zoomed in screenshot you see the image seems to have waves (not straight lines) this is not a good example but it is the best I could find fast. I have seem this happen with characters with fine Striped Black/White trousers that when I exit full screen then the picture of that clothe becomes wavy.

ksnip_20220415-021350 ksnip_20220415-021130

rezad1393 commented 2 years ago

better? P.S. I am not a human.

hooke007 commented 2 years ago

a 480p movie that is 720x480 on my screen in full screen would be shown in my screen at a 1440x960 and not 1620x1080.

video-unscaled=yes
video-zoom=1
rezad1393 commented 2 years ago

video-unscaled=yes video-zoom=1

beautiful. just one issue. that works only in fullscreen. is it way mroe work (or maybe an script) that integer-zooms based on window size? and this messes with higher than screen size videos. like 4k on my 1080 screen.

hooke007 commented 2 years ago

that works only in fullscreen.

Sounds weird , it works both in windowed and fullscreen here.

is it way mroe work (or maybe an script) that integer-zooms based on window size?

no idea.

and this messes with higher than screen size videos. like 4k on my 1080 screen.

Try to use the extra profile to limit it. But it's not descaling in integer.

[downscale-big]
 profile-cond = p["video_params/w"]>=1080
 profile-restore = copy
 video-unscaled=downscale-big
 video-zoom=0
hooke007 commented 2 years ago

Another temp solution. looks noob but useful.

mpv.conf

video-unscaled=yes

input.conf

F1 cycle-values video-zoom -1 0 1
F2 cycle-values video-zoom 1 0 -1
rezad1393 commented 2 years ago

that works only in fullscreen.

Sounds weird , it works both in windowed and fullscreen here.

is it way mroe work (or maybe an script) that integer-zooms based on window size?

no idea.

and this messes with higher than screen size videos. like 4k on my 1080 screen.

Try to use the extra profile to limit it. But it's not descaling in integer.

[downscale-big]
 profile-cond = p["video_params/w"]>=1080
 profile-restore = copy
 video-unscaled=downscale-big
 video-zoom=0

I wrote that in haste. I mean that the solution provided just kinda disables zoom. which is nice but not exactly as was posted in the topic. for example if I show a 640x360 video it shows it as 1280x720 and not 1920x1080 which is just 640x360 multiplied by 3.

also when I open it in window mode I think it opens it in 360p window but shows the video as a 720p so just center of video is shown.

rezad1393 commented 2 years ago

from this F1 cycle-values video-zoom -1 0 1 F2 cycle-values video-zoom 1 0 -1

I know learned about zoom levels in mpv :) thank you. btw -1 is half? and 0 is no zoom and 1 is zoom by 2?

I think the best I can get is to set the default mode at video-unscaled=downscale-big and then use cycle-values video-zoom. but the issue is that video-zoom doesn't have integer level option. " --video-zoom= Adjust the video display scale factor by the given value. The parameter is given log 2. For example, --video-zoom=0 is unscaled, --video-zoom=1 is twice the size, --video-zoom=-2 is one fourth of the size, and so on." so it only works in powers of 2.

hooke007 commented 2 years ago

That's why i said "temp solution". Also I don't use downscale-big as default. For those videos which is larger than you windowsize, it will firstly zoom-in to the windowsize, and then apply the video-zoom e.g. 1440p→\<your windowsize>→ video-zoom -1 (half of windowsize)

rezad1393 commented 2 years ago

That's why i said "temp solution". Also I don't use downscale-big as default. For those videos which is larger than you windowsize, it will firstly zoom-in to the windowsize, and then apply the video-zoom e.g. 1440p→→ video-zoom -1 (half of windowsize)

so you can disable video-zoom (use default mpv config) and use just cycling for videos you want.

but for that mpv needs to support zooms that are not numbers that are powers of 2. which I opened a ticket here. https://github.com/mpv-player/mpv/issues/10101

another way is this

video-unscaled=downscale-big
video-zoom=0

this way video is shown at the start at zoom-out and making window bigger stretches the video unless it is in its natural size and making window bigger than that doesn't zoom anymore ,unless video is bigger than your whole screen which is expected behavior.

I think I go the second way and wait for zoom to be fixed for non-2 powered integers.

btw, was I kinda right that zooms in non integer mode can be an issue for image fidelity? this is an issue for every image and not an mpv or even linux or even screen world, right? even when you want to print an image with a print , that printer has a resolution and your image has one two. now usually the printer has way higher resolution (minimum 600dpi) than your picture but if I force a non integer scale from image to paper, somewhere a decision has to be made to show a pixel that is not exactly correspond with a pixel in source.

I think if QLED or another technology gets to a point that screen with complete blacks (or even transparent screen) becomes the norm everywhere then a lot of the issues of video playing would disappear . the simplest one the infamous black bars at top-bottom or sides, but also after a large displays can be in square or circles shape and aspect ration would not matter for videos what much because screen would adapt to movie. but that is for screens in feature.

Dudemanguy commented 2 years ago

I'm sorry, I'm not sure I fully understand the request here. If you want to use zoom but at only integer scale multiples, you can. You could setup something in input.conf that would do the trick. Admittedly the numbers for 3x and such aren't so pretty, but you could cycle through a 1x/2x/etc. or whatever you need. As for the claim that integer scale zooms preserve fidelity, I don't think that's necessarily always true (maybe I'm wrong; didn't do any math to confirm it though).

Anyways, wayland further complicates the picture here because there will always be extra loss of quality, no matter what, if you use fractional scaling because of how it works.

rezad1393 commented 2 years ago

I'm sorry, I'm not sure I fully understand the request here. If you want to use zoom but at only integer scale multiples, you can. You could setup something in input.conf that would do the trick. Admittedly the numbers for 3x and such aren't so pretty, but you could cycle through a 1x/2x/etc. or whatever you need. As for the claim that integer scale zooms preserve fidelity, I don't think that's necessarily always true (maybe I'm wrong; didn't do any math to confirm it though).

Anyways, wayland further complicates the picture here because there will always be extra loss of quality, no matter what, if you use fractional scaling because of how it works.

thanks for reading my post. you got my issue almost. I meant for mpv to set the biggest integer zoom automatically based on window size. I learn about zoom levels and cycles and that helps a lot and almost solved 80% of my issue but I want to make it automatic based on window size and video resolution.

about wayland , I am way ahead of you :) I even reported this https://bugs.kde.org/show_bug.cgi?id=452261 and learn about the fu..kery that is wayland fractional scaling. and as I said in the first post, the wayland issue is for wayland and right now I use X11. and there is nothing mpv can do untill wayland fixes this upstream.

also about "As for the claim that integer scale zooms preserve fidelity, I don't think that's necessarily always true (maybe I'm wrong; didn't do any math to confirm it though)." the math is not genius level. it is not even math.

a pixel in image that is smaller than screen has to result in a pixel on screen (1to1, zero zoom) or multiple same exact group pixels as a square 2x2 or 3x3 and so on(integer zoom) or in non-integer zoom-in in used then a pixel from image will depend on other pixel beside it and the way the image viewer computes the result pixels on screen from groups of pixel in image.

if the last part is not obvious , make the question simple and go backward from screen to picture source. when you zoom in a picture that is say 4x4 on a 9x9 screen and use integer zoom you get a 8x8 picture on a 9x9 (with black bars or transparent bars at edges) and every pixel in than 8x8 can be traced back to just one pixel in image source. but when you use fullscreen zoom and get 9x9 image painted on the screen from a 4x4 image then you can be sure not one of the pixels on screen can be traced back to just one pixel from image.

even simpler way of saying this is this: if I give you a pixel by pixel integer-zoomed in result on a screen, you can get the source exactly back. but if I give you a non-integer result pixel by pixel, you cant give me back the source unless you have the algorithm that the image viewer used to show zoom that image and even then most of the time functions used are one-way functions (like password hashes) and you cant go back from result to source.

another way of saying it that a resulting image scaled non-fractionally(integer mode) will be the same in any program but fractional zoom depend on method used.

you can see this in many picture viewer apps that have a section for scaling method used. like mcomix app has under "edit -> preferences -> display --> image quality --> scaling mode : normal (fast), biliniar ,hyperbolic you can learn more about that here https://www.youtube.com/watch?v=R9mnjPgDCQk

but in integer-zoom non of that needs to happen and you just copy one pixel from source to 2x2 or 3x3 and so on and you can revert from 2x2 on result to one pixel back in source.

sorry for my bad english. this small github text area doesn't help either. hope that clarifies it.

P.S: image fidelity is not about image beauty. those image viewer use those scaling methods to make the images smoother.

if you search google for "image fractional scaling" you see many many academic papers for just that.

Dudemanguy commented 2 years ago

Integer zoom is not the same as integer scaling. If you have a 1920x1080 source image and you zoom in 2x on it, then what you are doing is viewing a 960x540 subsection blown up in a 1920x1080 image. This works out perfectly since 2 is a perfectly divides the width and height without leaving a remainder. Naturally, that's not always guaranteed. At a 7x, 1920x1080 would break apart and return fractions which means that rounding must be done at some step.

I learn about zoom levels and cycles and that helps a lot and almost solved 80% of my issue but I want to make it automatic based on window size and video resolution.

This sounds like it should be a script. You can observe the the osd-dimensions and dwidth/dheight properties and set the zoom levels to what suits you.

rezad1393 commented 2 years ago

when I used the word zoom I meant scaling (as in zooming in and blowing up the picture to be bigger) and you are right. I should have used the correct word but I didn't because English in not my language. but I did use a lot of "scaling" and "scale" too. should I change the title?

but all I said still apply if you change the word zoom to scale, right?

about the second part, I am not familiar with scripts. can you give me a sample? you mean lua scripts that I alluded to here? "but if my suggestion can be implemented as an option (or maybe a script) then a 480p movie that is 720x480 on my screen in full screen would be shown in my screen at a 1440x960 and not 1620x1080."

an example that works with window resized would be nice.

also

At a 7x, 1920x1080 would break apart and return fractions which means that rounding must be done at some step.

no. zoom in is the same as scaling up. scaling just implies that you has enough screen to show the result. for 7x zoom, image a 7x scaled up image that just the center is shown. if you meant that some pixel are not shown at the edges that is correct but pixel that are shown are exact replica only scaled up.

rezad1393 commented 2 years ago

P.S. this is for geometric values I think but pixels are technically just numbers. https://homepages.inf.ed.ac.uk/rbf/HIPR2/scale.htm

Dudemanguy commented 2 years ago

when I used the word zoom I meant scaling

Oh, now I see what you mean. That's actually quite a big difference. ;) Yes, in that case, mpv doesn't have such a feature. One could maybe emulate it by using a script, but it would probably get tricky.

zoom in is the same as scaling up. scaling just implies that you has enough screen to show the result.

The latter makes a big difference. I don't want to belabor this too much since you didn't actually mean "zoom", but when one says "integer scaling" they typically mean that you just nearest neighbor scale to the highest possible integer value that fits your screen. This could be 2x/4x/whatever but it's already implied that it's a "perfect' scale. When one zooms in on an image, there is no such guarantee that the zoom in level will evenly fit the window. I don't mean pixels off the screen either. I mean the actual pixels you are zoomed in on. For instance, zooming in 7x on a 1920x1080 image means you are looking at a 274.2857142857143x154.28571428571428 subsection of the total image. Obviously, this is not a perfect fit since the pixels on your screen aren't fractions. That means there is loss.

rezad1393 commented 2 years ago

when I used the word zoom I meant scaling

Oh, now I see what you mean. That's actually quite a big difference. ;) Yes, in that case, mpv doesn't have such a feature. One could maybe emulate it by using a script, but it would probably get tricky.

zoom in is the same as scaling up. scaling just implies that you has enough screen to show the result.

The latter makes a big difference. I don't want to belabor this too much since you didn't actually mean "zoom", but when one says "integer scaling" they typically mean that you just nearest neighbor scale to the highest possible integer value that fits your screen. This could be 2x/4x/whatever but it's already implied that it's a "perfect' scale. When one zooms in on an image, there is no such guarantee that the zoom in level will evenly fit the window. I don't mean pixels off the screen either. I mean the actual pixels you are zoomed in on. For instance, zooming in 7x on a 1920x1080 image means you are looking at a 274.2857142857143x154.28571428571428 subsection of the total image. Obviously, this is not a perfect fit since the pixels on your screen aren't fractions. That means there is loss.

thanks for clarification. as I said not an english boy.

but a point. that 7x would mean just edge pixels not whole section. that .2857142857143 would be just removed. you would lose a pixel but the other pixel are completely "scaled"