mpv-player / mpv

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

Unable to view large images on OpenGL video output #4264

Open rr- opened 7 years ago

rr- commented 7 years ago

mpv version and platform

mpv git-a993a871e (C) 2000-2017 mpv/MPlayer/mplayer2 projects
 built on Thu Mar 23 17:14:22 CET 2017
ffmpeg library versions:
   libavutil       55.34.101
   libavcodec      57.64.101
   libavformat     57.56.101
   libswscale      4.2.100
   libavfilter     6.65.100
   libswresample   2.3.100
ffmpeg version: 3.2.4

Reproduction steps

Try to open large file:

wget -O ~/mars.jpg "https://upload.wikimedia.org/wikipedia/commons/2/28/'Calypso'_Panorama_of_Spirit's_View_from_'Troy'.jpg"
mpv ~/mars.jpg --no-config --loop-file=inf --profile=opengl-hq

Expected behavior

I should see planet Mars

Actual behavior

I see black window instead

I can see the image fine on vo=x11, however, vo=opengl,x11 doesn't fall through onto x11. Suspected cause - my GPU can't handle GL textures this big, and the error happens too late to be caught by the code that would fall back to x11.

Log file

[playlist] Reading plaintext playlist.
Playing: /home/rr-/mars.jpg
 (+) Video --vid=1 (mjpeg)
[ffmpeg/video] mjpeg: overread 8
[ffmpeg/video] mjpeg: EOI missing, emulating
VO: [opengl] 23123x5093 yuv444p
[vo/opengl] after video texture creation: OpenGL error INVALID_VALUE.
[vo/opengl] after creating framebuffer texture: OpenGL error INVALID_VALUE
[vo/opengl] Error: framebuffer completeness check failed (error=36054).
[vo/opengl] after rendering: OpenGL error INVALID_FRAMEBUFFER_OPERATION.
[vo/opengl] after creating framebuffer texture: OpenGL error INVALID_VALUE
[vo/opengl] Error: framebuffer completeness check failed (error=36054).
[vo/opengl] after rendering: OpenGL error INVALID_FRAMEBUFFER_OPERATION.
[vo/opengl] after creating framebuffer texture: OpenGL error INVALID_VALUE
[vo/opengl] Error: framebuffer completeness check failed (error=36054).
[vo/opengl] after rendering: OpenGL error INVALID_FRAMEBUFFER_OPERATION.
[vo/opengl] after creating framebuffer texture: OpenGL error INVALID_VALUE
[vo/opengl] Error: framebuffer completeness check failed (error=36054).
[vo/opengl] after rendering: OpenGL error INVALID_FRAMEBUFFER_OPERATION.
[vo/opengl] after creating framebuffer texture: OpenGL error INVALID_VALUE
[vo/opengl] Error: framebuffer completeness check failed (error=36054).
[vo/opengl] after rendering: OpenGL error INVALID_FRAMEBUFFER_OPERATION.
V: 00:00:00 / 00:00:01 (0%)
[vo/opengl] after rendering: OpenGL error INVALID_FRAMEBUFFER_OPERATION.
[vo/opengl] after rendering: OpenGL error INVALID_FRAMEBUFFER_OPERATION.
[vo/opengl] after rendering: OpenGL error INVALID_FRAMEBUFFER_OPERATION.
[vo/opengl] after rendering: OpenGL error INVALID_FRAMEBUFFER_OPERATION.
[vo/opengl] after rendering: OpenGL error INVALID_FRAMEBUFFER_OPERATION.
[vo/opengl] after rendering: OpenGL error INVALID_FRAMEBUFFER_OPERATION.
[vo/opengl] after rendering: OpenGL error INVALID_FRAMEBUFFER_OPERATION.
[vo/opengl] after rendering: OpenGL error INVALID_FRAMEBUFFER_OPERATION.
[vo/opengl] after rendering: OpenGL error INVALID_FRAMEBUFFER_OPERATION.
[vo/opengl] after rendering: OpenGL error INVALID_FRAMEBUFFER_OPERATION.
V: 00:00:00 / 00:00:01 (0%)

Exiting... (Quit)

Sample files

https://upload.wikimedia.org/wikipedia/commons/2/28/'Calypso'_Panorama_of_Spirit's_View_from_'Troy'.jpg

ghost commented 7 years ago

Such is life. I'm surprised FFmpeg still accepts this dimension - it must be close to the limit (which is about 10000*10000 pixels).

Best we could do is "pre-scaling" the image with libswscale.

rr- commented 7 years ago

Will that work with zooming and panning though? (e.g. if I zoom in, won't I be seeing downscaled-and-then-upscaled texture?)

ghost commented 7 years ago

You can try how that would work by using --vf=scale=... (vf_scale's options suck, there's no scale factor and you must pass a new size).

I think current hardware has texture limits from 4K x 4K to 32K x 32K (depends on the GPU).

rr- commented 7 years ago

Unfortunately it looks pretty bad, especially for highly detailed images...

It would be cool to be able to fit the texture on the viewport rather than source, and use sws to fit and translate the image into that viewport texture. (I think that's what already happens with vo=x11 - of course with mmap()ed or similar pixels, rather than GL textures?)

Also if you zoom a large image close enough on vo=x11, the image gets stretched in a weird way. (I think the image size overflows?) The behavior seems to produce different artifacts for large image width and for large image height.

ghost commented 7 years ago

Well sure, with vo_x11 this will work better, because it involves cropping the image before libswscale, and then scaling the cropped image to screen size.

I don't know what's overflowing, or whether it's a mpv or libswscale bug.

rr- commented 7 years ago

Because x11 seems to have no problem with images of such size, I'd use x11 by default, but x11 flickers a lot when switching between images, and xv (which seems to work similarly to x11) has suboptimal OSD scaling.

For this reason I think the optimal solution (good looks and presumably low effort) is to make -vo=opengl,... fall back to the next VO when opengl is unable to create the texture - that way, supplying -vo=opengl,x11, would trigger x11 only for extreme images.

(The other solution I have in mind is to make a backend / wrapper for OpenGL that uses SWS to crop and scale the image into a texture of reasonable size.)

haasn commented 7 years ago

The “proper” fix would be to use tiled textures for images too large to fit inside a single texture, but unfortunately getting this to work properly would be pretty complicated.

ghost commented 7 years ago

Too complicated, except maybe as explicit downsample pass (which would disregard some correctness issues).

qmega commented 7 years ago

Out of curiosity, what would be the complications? I've been planning to write an image viewer and this issue had occurred to me. I figured the tiles would have to overlap by the radius of the scaler. What else would have to be done?

ghost commented 7 years ago

I figured the tiles would have to overlap by the radius of the scaler.

I guess this might work too. Still pretty complicated...

haasn commented 7 years ago

They would have to overlap, yes. But working that logic into vo_opengl would still be stupidly complicated, given that vo_opengl has more than enough things going on.

That said, I think you could completely abstract it away and hide it behind a unified pseudotexture that works the same way as they do currently, with the only cost being the need to draw multiple tris with updated bindings.

BGodding commented 3 months ago

Did you ever find a workaround for this? Running into the same issue when trying to use a playlist with mixed videos and images. Images > GL_MAX_TEXTURE_SIZE fail to load unless I am using x11, but the video performance on x11 is poor. Currently I am using the command interface to dynamically change vo when a large image needs to be displayed, but that can cause some glitching during the transition.